我对使用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
答案 0 :(得分:6)
这是合乎逻辑的,因为给定签名为2个元组的列表,并且您的deal xs
和deal 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 . (:)) ([], [])