为什么第三个让入语句出错?

Sus*_*han -2 haskell

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 :: forall a时。(Num a,Num [a])=> a
在表达式中:let x:y = 3:4 in x * x + y * y
在'it'的等式中:it = let x:y = 3:4在x * x + y * y中

有人可以解释前两个语句中发生了什么以及为什么第三条let ... in ..语句有错误。

Bil*_*own 6

在第三个示例中,let分配的右侧是:3:4。该:(缺点)运算符的类型签名a -> [a] -> [a]:它需要在其左侧的值,并在右侧该类型的值的列表。在这种情况下,3a,但4不是a[a])的列表;这也是一个a。这是无效的。

鉴于到目前为止的锻炼形式,您可以通过两种方法解决此问题:with 3:[4]或with 3:4:[]

如果您现在尝试运行代码,则会发现它在上失败x * x + y * y。这是因为你的模式匹配受让人x3,并y[4](一个单列表)。列表本身不能相乘,也不能添加到数字中。因此,我们再次在左侧使用解决方案:

let x:y:[] = 3:4:[]
    in x * x + y * y
Run Code Online (Sandbox Code Playgroud)

如果我们添加了太多的类型注释,则可以希望看到问题出在哪里:

-- 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
Run Code Online (Sandbox Code Playgroud)