没有完全类型知识的Haskell多态调用

没有完全类型知识的Haskell多态调用,haskell,types,polymorphism,Haskell,Types,Polymorphism,我从一段时间开始学习Haskell,所以我是个新手 以下代码非常容易理解: purStrLn $ show [1] 在这里,我们可以推断出所有类型(带有默认值),并且所有类型都工作得很好。 但以下代码也可以工作: putStrLn $ show [] 即使我们无法推断列表类型 如果我使用ghci执行代码,我将获得以下信息: Prelude> [] [] Prelude> :t it it :: [a] Prelude> 因此,该类型似乎是多态的。但在这种情况下,将使用部

我从一段时间开始学习Haskell,所以我是个新手

以下代码非常容易理解:

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这很有趣!我必须获得更深的理解,这是肯定的!