spi*_*ire 2 haskell functional-programming
我真的不知道为什么这是一个类型错误:
foo :: (Eq a) => a -> a
foo _ = 2
Run Code Online (Sandbox Code Playgroud)
谁能解释一下?
Mic*_*ski 14
因为类型
foo "bar"
Run Code Online (Sandbox Code Playgroud)
应该是String,根据你的签名,但不是(2不是字符串).在你的代码中,foo是通用的,所以它应该返回一个与参数完全相同的实例.
haskell类型系统的强大功能为我们提供了额外的信息 - 你可以用foo中的参数来检查它与其他东西的相等性,但是我可以想出任何新的类型(让我们称之为Baz)并使用foo它 - 你不可能有任何其他Baz实例,所以返回Baz实例的唯一方法是返回与参数完全相同的实例.
如果你像这样重写了foo:
foo _ = True
Run Code Online (Sandbox Code Playgroud)
它会有一个签名foo :: a -> Bool
,这基本上是你试图做的,但事情变得更复杂的数字.
一般来说,您的功能有一个签名
foo :: (Num t1) => t -> t1
Run Code Online (Sandbox Code Playgroud)
这意味着它为任何给定的参数返回一个Num实例.(这是因为2可以在haskell中有许多不同的类型,取决于你需要它可以是Int或Real或其他.)
您应该使用ghci中的类型,例如:
:t foo
Run Code Online (Sandbox Code Playgroud)
会给你foo的感染型签名.
:t 2
Run Code Online (Sandbox Code Playgroud)
给出了(Num t) => t
哪个意味着2可以是实现Num的任何类型的实例.
您声明的类型签名意味着
对于所有类型
a
(实例化Eq),foo
获取此类型的值并返回此类型的另一个值
你甚至可以这样直接写它:
foo :: forall a . Eq a => a -> a
Run Code Online (Sandbox Code Playgroud)
现在是函数定义
foo _ = 2
Run Code Online (Sandbox Code Playgroud)
说了些不同的话:
无论给出什么类型,都要返回一个数字.
当然这种类型是不相容的.
示例:正如Michał所说,既然foo "Hello"
给了a String
,它应该返回一个字符串,但实际上确实返回一个数字.