首页 > 解决方案 > Haskell:错误无法匹配预期类型

问题描述

有人可以帮助我弄清楚我在这段代码中做错了什么。我尝试编写一个添加两个多项式函数的代码,但我总是收到以下错误消息:

main.hs:6:45: error:
    * Couldn't match expected type `[a]' with actual type `Poly a'
    * In the second argument of `(:)', namely `polyadd (P xs) (P ys)'
      In the first argument of `P', namely
        `((x + y) : polyadd (P xs) (P ys))'
      In the expression: P ((x + y) : polyadd (P xs) (P ys))
    * Relevant bindings include
        ys :: [a] (bound at main.hs:6:26)
        y :: a (bound at main.hs:6:24)
        xs :: [a] (bound at main.hs:6:15)
        x :: a (bound at main.hs:6:13)
        polyadd :: Poly a -> Poly a -> Poly a (bound at main.hs:4:1)
  |
6 | polyadd (P (x:xs)) (P (y:ys))  = P ((x+y) : polyadd (P xs) (P ys))
  |                                             ^^^^^^^^^^^^^^^^^^^^^

这是我的代码

data Poly a = P [a] deriving (Show, Eq)

polyadd :: (Num a, Eq a) => Poly a -> Poly a -> Poly a
polyadd (P ([])) (P (ys))          = P ys
polyadd (P (xs)) (P [])          = P xs
polyadd (P (x:xs)) (P (y:ys))  = P ((x+y) : polyadd (P xs) (P ys))

标签: haskell

解决方案


在这个表达式中:

(x+y) : polyadd (P xs) (P ys)

您正在尝试通过将 head 附加到 tail来创建列表。这就是运营商的意思。这就是它的作用。从头部和尾部创建一个列表。(x+y)polyadd (P xs) (P ys)(:)

问题是,列表的尾部应该是列表,但polyadd (P xs) (P ys)不是列表,而是Poly a类型签名中定义的 a 。所以它不适合 operator (:),它期望它的右操作数是一个列表。所以编译器会准确地告诉你:无法将预期类型 '[a]' 与实际类型 'Poly a' 匹配

根据我的读心能力告诉我你的意图,你真正想做的是预先(x+y)添加到包含Poly a. 为此,您必须解构第Poly a一个:

polyadd (P (x:xs)) (P (y:ys))  = 
  let (P zs) = polyadd (P xs) (P ys)
  in P ((x+y) : zs)

Poly a但是当然,不要在每一步打开和重新包装值,而是先构造结果列表,然后再包装它,这样会更干净、更有效。为此,您需要一个单独的函数来执行列表遍历,然后调用该函数,并将其结果包装在Poly

polyadd :: (Num a, Eq a) => Poly a -> Poly a -> Poly a
ployadd (P as) (P bs) = P (inner as bs)
  where
    inner [] ys = ys
    inner xs [] = xs
    inner (x:xs) (y:ys) = (x+y) : inner xs ys

推荐阅读