Prelude> let [x,y] = [3,4] in x*x+y*y
25
Prelude> let x:[y] = [3,4] in x*x + y*y
25
Prelude> let x:y = 3:4 in x*x+y*y
交互式:6:5:错误:
*约束中的非类型变量参数:Num [a]
(使用FlexibleContexts允许此操作)
*检查推断类型时
x ::全部(数字a,数字[a])=> a
在表达式中:让x:y = 3:4 in x * x + y * y
在“ it”的等式中:it = let x:y = 3:4 in x * x + y * y
有人可以解释一下前两个语句中发生了什么,为什么第三个let ... in ..
语句有错误。
答案 0 :(得分:6)
在第三个示例中,let
分配的右侧为:3:4
。 :
(cons)运算符的类型签名为a -> [a] -> [a]
:它的左侧带有一个值,右侧带有该类型的值的列表。在这种情况下,3
是a
,但是4
不是a
([a]
)的列表;它也是a
。这是无效的。
鉴于到目前为止的锻炼形式,有两种方法可以解决此问题:3:[4]
或3:4:[]
。
如果现在尝试运行代码,您会发现它在x * x + y * y
上失败。这是因为您的模式匹配将x
分配给3
,并且将y
分配给[4]
(单例列表)。列表本身不能相乘,也不能添加到数字中。因此,我们再次在左侧使用解决方案:
let x:y:[] = 3:4:[]
in x * x + y * y
如果我们添加了太多的类型注释,则可以希望看到哪里出了问题:
-- These work fine
-- let [x, y] = [3, 4] in ...
example1 = let [(x :: a), (y :: a)] :: [a]
= [(3 :: a), (4 :: a)] :: [a]
in x * x + y * y
-- let x:[y] = [3, 4] in ...
example2 = let ((x :: a) : ([(y :: a)] :: [a])) :: [a]
in x * x + y * y
-- This is the incorrect implementation
-- let x:y = 3:4 in ...
example3 :: (Num a) => a
example3 = let (x :: a) : (y :: [a]) -- (:) :: a -> [a] -> [a]
= (3 :: a) : (4 :: a) -- 4 :: a is invalid here: require [a]
in (x :: a) * (x :: a)
+ (y :: [a]) * (y :: [a]) -- Trying to multiply two lists
-- This is the fixed implementation
-- let x:y:[] = 3:4:[] in ...
example3' :: (Num a) => a
example3' = let ((x :: a) : (y :: a) : ([] :: [a])) :: [a]
= ((3 :: a) : (4 :: a) : ([] :: [a])) :: [a]
in x * x + y * y