无法将预期类型'[a1]'与实际类型'([a1],[a1])'相匹配

时间:2019-09-03 08:57:26

标签: haskell

我对使用Haskell进行编码并不陌生,并且坚持使用我的教授希望我们编写的代码。我应该像这样将一个列表分成一对列表:

deal [1,2,3,4,5,6,7] = ([1,3,5,7], [2,4,6])

但是我在“ xs”和“ ys”上都收到此错误

* Couldn't match expected type `[a1]'
                  with actual type `([a1], [a1])'
    * In the expression: deal xs
      In an equation for `xs': xs = deal xs
      In an equation for `deal':
          deal (x : y : xs : ys)
            = (x : xs, y : ys)
            where
                xs = deal xs
                ys = deal ys
    * Relevant bindings include xs :: [a1] (bound at lab2.hs:16:17)
   |
   |                 xs = deal xs
   |                      ^^^^^^^

这是我的代码:

deal :: [a] -> ([a],[a])
deal [] = ([], [])
deal [x] = ([x], [])
deal (x:y:xs:ys) = (x:xs,y:ys)
    where
        xs = deal xs
        ys = deal ys

1 个答案:

答案 0 :(得分:6)

这是合乎逻辑的,因为给定签名为2个元组的列表,并且您的deal xsdeal ys将返回xs,这是合乎逻辑的。请注意,通过使用相同的名称,您在此处创建了递归表达式,该表达式不起作用。多次使用相同的名称不是一个好主意。如果打开警告,则编译器通常会对此发出警告。

您可能想调用列表[a]上的deal,然后检索用作尾巴的两个列表:

rest

或者我们可以使用(***) :: a b c -> a b' c' -> a (b, b') (c, c')

deal :: [a] -> ([a],[a])
deal [] = ([], [])
deal [x] = ([x], [])
deal (x:y:rest) = (x:xs, y:ys)
    where (xs, ys) = deal rest

另一种选择是每次交换元组,然后追加到另一侧:

import Control.Arrow((***))

deal :: [a] -> ([a],[a])
deal [] = ([], [])
deal [x] = ([x], [])
deal (x:y:rest) = ((x:) *** (y:)) (deal rest)

因此,我们可以将其定义为import Control.Arrow(first) import Data.Tuple(swap) deal :: [a] -> ([a],[a]) deal [] = ([], []) deal (x:xs) = first (x:) (swap (deal xs))模式:

foldr

这给了我们预期的结果:

import Control.Arrow(first)
import Data.Tuple(swap)

deal :: Foldable f => f a -> ([a],[a])
deal [] = foldr ((. swap) . first . (:)) ([], [])