Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何绕过F#和#x27;s型系统_Haskell_F# - Fatal编程技术网

Haskell 如何绕过F#和#x27;s型系统

Haskell 如何绕过F#和#x27;s型系统,haskell,f#,Haskell,F#,在Haskell中,可以使用unsafeccerce覆盖类型系统。在F#中如何做同样的事情 例如,要在Haskell中实现Y-combinator。,unsafeccerce具有类型a->b,通常用于向编译器断言被强制的对象实际上具有目标类型,只是类型检查器不知道它 另一个不太常见的用法是将位模式重新解释为另一种类型。例如,未装箱的Double可以重新解释为未装箱的Int64。为了安全起见,您必须确定底层表示 在F#中,第一个应用程序可以通过box |>unbox实现,正如John Palmer

在Haskell中,可以使用
unsafeccerce
覆盖类型系统。在F#中如何做同样的事情


例如,要在Haskell中实现Y-combinator。

unsafeccerce
具有类型
a->b
,通常用于向编译器断言被强制的对象实际上具有目标类型,只是类型检查器不知道它

另一个不太常见的用法是将位模式重新解释为另一种类型。例如,未装箱的
Double
可以重新解释为未装箱的
Int64
。为了安全起见,您必须确定底层表示

在F#中,第一个应用程序可以通过
box |>unbox
实现,正如John Palmer在对该问题的评论中所说的那样。如果可能,请使用显式类型参数以确保不会意外推断出错误的强制,例如,
box
,其中
'a
'b
是类型变量或已在代码范围内的具体类型

对于第二个应用程序,请查看特定的位模式转换。理论上,您也可以使用非托管代码来实现这一点,但这似乎非常重要


这些技术不适用于实现Y combinator,因为只有当运行时对象确实具有目标类型时,强制转换才有效,但使用Y combinator时,您实际上需要再次调用相同的函数,但使用不同的类型。为此,您需要中提到的各种编码技巧。

我想提供一种不同的解决方案,基于在类型化函数语言中嵌入非类型化的lambda演算。其思想是创建一种数据类型,允许我们在类型α和α之间进行更改→ α、 它随后允许摆脱类型系统的限制。我对F#不是很熟悉,所以我会用Haskell给出我的答案,但我相信它很容易适应(也许唯一的复杂因素可能是F#的严格性)

——|大致表示@a@和@a->a@.
--因此,我们可以在@Any中嵌入任意闭合λ项a@. 任何时候我们
--需要创建一个λ-抽象,我们只需嵌套到一个@Any@构造函数中。
--
--type参数允许我们将普通值嵌入类型和
--检索计算结果。
数据任意a=任意(任意a->a)
请注意,类型参数对于组合术语并不重要。它只允许我们将值嵌入到表示中,并在以后提取它们。特定类型的所有术语
任何a
都可以自由组合而不受限制

——|将值嵌入λ-项。如果将其视为函数,则会忽略其
--输入并生成值。
嵌入::a->任意a
嵌入=任何。常数
--|从λ-项中提取一个值,假设它是一个有效值(否则
--循环(永远)。
摘录::任意a->a
提取x@(任意x')=x'x
使用此数据类型,我们可以使用它来表示任意非类型化的lambda术语。如果我们想将
anya
的值解释为一个函数,我们只需打开它的构造函数

首先,让我们定义函数应用程序:

——|将一个术语应用于另一个术语。
($$)::任意a->任意a->任意a
(任意x)$$y=嵌入$x y
和λ抽象:

——|表示lambda抽象
l::(任意a->任意a)->任意a
l x=任何$extract。x
现在我们有了创建复杂λ项所需的一切。我们的定义模仿了经典的λ-术语语法,我们所做的就是使用
l
构造λ抽象

让我们定义Y组合子:

——λf.(λx.f(xx))(λx.f(xx))
y:有a吗
y=l(\f->let t=l(\x->f$$(x$$x))
以t$$t为单位)
我们可以用它来实现Haskell经典的
修复
。首先,我们需要能够将
a->a
的函数嵌入
任意a

embed2::(a->a)->任何a
嵌入2 f=任何(f.提取)
现在定义起来很简单

fix::(a->a)->a
固定f=提取(y$$embed2 f)
然后是递归定义的函数:

fact::Int->Int
事实=修正f
哪里
f 0=1
fRn=n*r(n-1)

请注意,在上面的文本中没有递归函数。唯一的递归是在
Any
数据类型中,它允许我们定义
y
(它也是非递归定义的)。

:?>
也许-您可以提供一个更具体的示例来说明您想要什么。否则,
box |>unbox
可能适用于更新-请参见此处