1

我想围绕Haskell的语法包扎头脑。守卫和匿名函数列表

这个问题很简单,逻辑解决。我必须分解一个正整数和负整数的列表,并将它们分组,使得

[1,2,3,-1,-2,-3,1,2,3]变成[[1,2, 3],[ - 1,-2,-3],[1,2,3]]

我想使用更高阶的函数,foldr可以用一个匿名函数arguements。

这是我到目前为止。

split = foldr (\ x y -> if (x > 0) 
         then if (head (head y)) < 0 
          then [x] : y 
          else x : head y --error here 
         else if (x < 0) 
         then if (head (head y)) > 0 
          then [x] : y 
          else x : head y 
         else y 
       ) 
       [[]] 

这是错误我得到

Occurs check: cannot construct the infinite type: a0 = [a0] 
    In the first argument of `(:)', namely `x' 
    In the expression: x : head y 
    In the expression: 
     if (head (head y)) < 0 then [x] : y else x : head y 

我有两个问题。

1)为什么我在第7行出现类型错误?

我这不是连接来整数列表(头Y)

2)你怎么写出来的使用警卫下述条件的整数(X)?我试图做到这一点,但我一直收到parsing error at '|'

回答

1

你只是想保持tail y。在

foldr (\ x y -> if (x > 0) 
        then if (head (head y)) < 0 
         then [x] : y 
         else x : head y 

你有x :: (Num a, Ord a) => ay :: (Num a, Ord a) => [[a]]head y :: (Num a, Ord a) => [a]

因此,忘记tail y削减了一层[]。所述else分支应该是

else (x:head y) : tail y 
在外 if的两个分支

但是,之后你的函数有两个语义问题。

首先,您不要将head y为空的情况视为,当到达列表的末尾时会导致异常,其次,它无法在无限列表上工作,因为组合函数不会在' t在第二个参数已知之前构造任何结果。如果后者是一个问题,你可以找到一个足够懒惰的组合函数in this answer

+0

啊。非常感谢!如果说'拥有'x'头部',我不会在某种意义上“返回”列表的列表,而只是列表? – ali

+0

是的,这是问题所在。 –

2
  1. 一个函数只能有一个混凝土返回类型和[x] : y是从x : head y不同的类型。

  2. 它可能更容易将其与takeWhiledropWhile写:

    split l = split' (if head l > 0 then (>) else (<)) l 
        where split' op [] = [] 
         split' op l = takeWhile (`op` 0) l : split (dropWhile (`op` 0) l)