没有完全类型知识的Haskell多态调用
我从一段时间开始学习Haskell,所以我是个新手 以下代码非常容易理解:没有完全类型知识的Haskell多态调用,haskell,types,polymorphism,Haskell,Types,Polymorphism,我从一段时间开始学习Haskell,所以我是个新手 以下代码非常容易理解: purStrLn $ show [1] 在这里,我们可以推断出所有类型(带有默认值),并且所有类型都工作得很好。 但以下代码也可以工作: putStrLn $ show [] 即使我们无法推断列表类型 如果我使用ghci执行代码,我将获得以下信息: Prelude> [] [] Prelude> :t it it :: [a] Prelude> 因此,该类型似乎是多态的。但在这种情况下,将使用部
purStrLn $ show [1]
在这里,我们可以推断出所有类型(带有默认值),并且所有类型都工作得很好。
但以下代码也可以工作:
putStrLn $ show []
即使我们无法推断列表类型
如果我使用ghci执行代码,我将获得以下信息:
Prelude> []
[]
Prelude> :t it
it :: [a]
Prelude>
因此,该类型似乎是多态的。但在这种情况下,将使用部分应用的类型调用show
同样的行为在其他类型中也很常见,例如Data.Map.empty,因此它不是列表功能(或者至少看起来是这样)
为什么以及如何工作?首先,这只适用于
ghci
。如果您尝试使用ghc
编译此程序,您将得到一个类型错误:
Test.hs:3:19:
Ambiguous type variable `a0' in the constraint:
(Show a0) arising from a use of `show'
Probable fix: add a type signature that fixes these type variable(s)
In the second argument of `($)', namely `show []'
In the expression: putStrLn $ show []
In an equation for `main': main = putStrLn $ show []
添加类型签名会使错误消失:
module Main where
main = putStrLn $ show ([]::[Int])
但是为什么它在ghci中起作用呢?答案在ghci
中:a
的类型默认为()
(单位类型)
这种行为的动机是,用户在解释器中工作时总是指定类型,这有点令人厌烦。正如Vitus在评论中指出的,使用-Wall
运行ghci
(或将:set-Wall
添加到~/.ghci
)可以更容易地发现默认值:
<interactive>:2:12:
Warning: Defaulting the following constraint(s) to type `()'
(Show a0) arising from a use of `show'
In the second argument of `($)', namely `show []'
In a stmt of an interactive GHCi command: it <- putStrLn $ show []
:2:12:
警告:将以下约束默认为键入“()”
(Show a0)因使用“Show”而产生
在“($)”的第二个参数中,即“show[]”
在交互式GHCi命令的stmt中:在GHCi中键入:set-Wall
也有助于发现此默认值。很好,这是一个非常解释性的答案:)purStrLn$show[1]
仍然必须默认为一个类型,因为[1]:(Num n)=>[n]
这是真的,但在这种情况下也有默认值。请注意,当类型变量不受约束时,会发生其他情况,例如,length[]
,请参阅:。@hammar这很有趣!我必须获得更深的理解,这是肯定的!