Guards and concatiating to lists in an anonymous function

心已入冬 提交于 2019-12-11 05:13:38

问题


I am trying to wrap my head around the syntax of Haskell.

This problem is very simple to solve logically. I have to break up a list of positive and negative integers and group them such that

[1,2,3,-1,-2,-3,1,2,3] becomes [[1,2,3],[-1,-2,-3], [1,2,3]]

I would like to use a higher order function, foldr to be able to do that with an anonymous function taking in two arguements.

This is what I have so far.

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
                )
                [[]]

this is the error i get

 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

I have two questions.

1) Why am I getting a type error at line 7?

Am I not concatenation an integer (x) to a list of integers (head y)

2) How do you write the conditions out using guards? I tried doing it but I kept getting parsing error at '|'


回答1:


You're simply missing to keep tail y. In

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

you have x :: (Num a, Ord a) => a, y :: (Num a, Ord a) => [[a]], and head y :: (Num a, Ord a) => [a].

So forgetting the tail y shaves off one layer of []. the else branch should be

else (x:head y) : tail y

in both branches of the outer if.

But, your function has two semantic problems after that.

First, you don't treat the case that head y is empty, that will cause an exception when the end of the list is reached, and second, it doesn't work on infinite lists, since the combinator function doesn't construct anything of the result before its second argument is known. If the latter is a problem, you can find a sufficiently lazy combinator function in this answer.




回答2:


  1. A function can have only one concrete return type and [x] : y is a different type from x : head y.

  2. It's probably easier to write it with takeWhile and dropWhile:

    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)
    


来源:https://stackoverflow.com/questions/12883559/guards-and-concatiating-to-lists-in-an-anonymous-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!