Haskell:Num[a]=>;a`和'Num a=>;[a]`

Haskell:Num[a]=>;a`和'Num a=>;[a]`,haskell,types,typeclass,Haskell,Types,Typeclass,很明显,我的打字签名是错的。后来我发现了原因。现在,我想知道更多关于我打字错误上的GHCI推断签名的信息。我试图让这段代码正常工作: elemNum :: (Eq a, Num b) => a -> [a] -> b elemNum e l = f e l where f _ [] = [] -- this was my typo, supposed to read 0 f e (x:xs) | x == e = 1 + f

很明显,我的打字签名是错的。后来我发现了原因。现在,我想知道更多关于我打字错误上的GHCI推断签名的信息。我试图让这段代码正常工作:

elemNum :: (Eq a, Num b) => a -> [a] -> b
elemNum e l = f e l
  where  f _ [] = []  -- this was my typo, supposed to read 0
         f e (x:xs)
             | x == e = 1 + f e xs
             | otherwise = f e xs
由于上述原因,它显然不起作用;但是,如果我删除我的签名,它会编译(不确定为什么,请解释),我会得到这个签名:

elemNum :: (Num [a], Eq t) => t -> [t] -> [a]

我以前从未见过typeclass
Num[a]
。。这意味着什么?它与
(Num a)=>[a]
Num a
相比,意味着类型
a
可以被视为一个数字;例如,您可以将两个
a
s相加,得到一个新的
a
,也可以对
a
求反,得到一个
a
<代码>整数和
双精度
属于此类别

相应地,
Num[a]
意味着类型
[a]
可以被视为一个数字。也就是说,您可以将两个
a
列表相加,以获得一个新的
a
列表。这不太可能有意义,因为没有列表是数字(默认情况下)。这意味着您将列表视为一个数字,从而使GHC得出结论,您必须希望您的列表表现为一个数字,从而添加了一个适当的约束

此类约束可能来自以下函数:

foo (x:xs) = xs + 1

xs
作为列表的尾部进行模式匹配,因此它本身就是一个列表,然后您将添加到其中,将列表视为一个数字。

Num[a]约束意味着列表是Num类型类的实例

foo :: Num a => [a]
是Num类型类实例的值列表

bar :: Num [a] => [a]
是值列表,它本身就是Num类型类的实例。这意味着您可以使用Num中的所有函数,并从数值文本构造列表,因此下面的代码是有效的,尽管需要flexibleContext

bar :: Num [a] => [a]
bar = 42
另外,这里不需要helper函数。元素e l=f e l⇒ 元素=f。因此,您可以将函数编写为

elemNum _ [] = 0
elemNum e (x:xs)
  | x == e = 1 + f e xs
  | otherwise = f e xs

我可以让
[a]
成为
Num
的成员吗?如果可以,你能提供一个简单的例子吗?如果没有,为什么不呢?是的,你可以。例如,如果你想提供多项式,但总的来说这是个坏主意。实例Num a=>Num[a]其中fromIntegral a=[a](a:as)+(b:bs)=(a+b):(as+bs)[]+bs=bs-as+[]=as…从技术上讲,您可以通过执行
instance Num[a]其中fromIntegral x=undefined这样的操作使任何东西成为任何类型类的实例(提供的种类匹配);x+y=未定义
等。但显然没有用处。