lef*_*out 16 recursion haskell type-inference parametric-polymorphism
解决“ f = f(<*>)pure”类型提示了这一点,该类型讨论了一个更复杂的示例,但该示例也有效。
以下定义可以毫无问题地进行编译:
w :: Integral a => a
w = fromInteger w
Run Code Online (Sandbox Code Playgroud)
...当然,它在运行时无法正常工作,但这是个问题。问题的关键是,定义w本身使用的专用版本的w :: Integer。显然,这是一个合适的实例,因此进行类型检查。
但是,如果我们删除签名,那么GHC不会推断上述类型,而只能推断具体类型:
w' = fromInteger w'
Run Code Online (Sandbox Code Playgroud)
GHCi> :t w
w :: Integral a => a
GHCi> :t w'
w' :: Integer
Run Code Online (Sandbox Code Playgroud)
好吧,当我看到这一点时,我相当确定这是工作中的单态性限制。众所周知,例如
i = 3
Run Code Online (Sandbox Code Playgroud)
GHCi> :t i
i :: Integer
Run Code Online (Sandbox Code Playgroud)
虽然i :: Num p => p完全有可能。实际上,i :: Num p => p 可以推断出是否-XNoMonomorphismRestriction处于活动状态,即是否禁用了单态性限制。
但是,即使禁用了单态性限制,也w'只能Integer推断出类型。
要计算出这与默认设置有关:
fromFloat :: RealFrac a => Float -> a
q :: RealFrac a => a
q = fromFloat q
q' = fromFloat q'
Run Code Online (Sandbox Code Playgroud)
GHCi> :t q
q :: RealFrac a => a
GHCi> :t q'
q' :: FloatRun Code Online (Sandbox Code Playgroud)
为什么不能推断多态类型?
dfe*_*uer 19
多态递归(函数以与调用函数不同的类型调用自身)始终需要类型签名。完整的解释在《 Haskell 2010报告》的第4.4.1节中:
如果在
f没有提供相应类型签名声明的情况下定义了变量,则每次f在其自己的声明组之外使用(请参见第4.5节)都将被视为具有相应的推断类型或主体类型。但是,为了确保仍然可以进行类型推断,其定义f组中的定义出现及其所有使用都必须具有相同的单态类型(如4.5.2节所述,通过泛化可从中获得主体类型)。
后面的同一部分提供了由类型签名支持的多态递归的示例。
我的理解是,在存在多态递归的情况下,通常无法确定无助的类型推断,因此Haskell甚至不会尝试。
在这种情况下,类型检查器以
w :: a
Run Code Online (Sandbox Code Playgroud)
a元变量在哪里。由于在其自己的声明中(因此也在其声明组中)fromInteger将with w作为参数调用,因此类型检查器a与合并Integer。没有可归纳的变量。
出于相同的原因,对程序进行轻微的修改会得到不同的结果:
v = fromIntegral v
Run Code Online (Sandbox Code Playgroud)
根据您的原始推理,Haskell会推断v :: forall a. Num a => a,默认v将RHS上的输入为Integer:
v :: forall a. Num a => a
v = fromIntegral (v :: Integer)
Run Code Online (Sandbox Code Playgroud)
但是,它以开头v :: a。既然v通过了fromIntegral,就强加了Integral a。最后,概括了a。最后,程序证明是
v :: forall a. Integral a => a
v = fromIntegral (v :: a)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
341 次 |
| 最近记录: |