0


I'm trying to understand recursion with the functions of Haskell, but I have some problems with this function, in particular with foldr function:

I have declared a data Shape in this manner:

type P = (Int, Int)   -- point
type V = (Int, Int)   -- vector

data Shape = 
    Line P P                  -- line characterized by two vertices
    | Triangle P P P          -- characterized by three triangle vertices
    deriving (Eq, Show)

Now, given a list of forms, I have to extract the shape that has greater area

maxArea :: [Shape] -> Shape
maxArea list = maxArea_hlp list 0

maxArea_hlp :: [Shape] -> Int -> Shape
maxArea_hlp list areaMax = foldr (\shape currmax -> if ((area shape) > (area currmax)) then shape else (shape:list)) 0 list

area :: Shape -> Int
area (Line _ _) = 0
area (Triangle p1 p2 p3) = 0
--TODO

The error is:

Couldn't match expected type Shape with actual type [Shape]
In the expression: (shape : list)

The error lies in the "else" branch of the lambda function, but I do not understand how to solve it.

Can you help me please?
Thanks to all

4
  • 4
    What is the type of currmax supposed to be? According to the type signature of foldr ( (a -> b -> b) -> b -> [a] -> b), it should be numeric (the same as 0), but you also call area on it, which suggests that it should be Shape. There lies your mistake. Using foldr for this is awkward. Why not use maximumBy? Commented Mar 31, 2015 at 18:33
  • 6
    You're returning a Shape in one branch of the if and a [Shape] in the other branch, which doesn't type-check. Is there a particular reason you're using foldr here instead of Data.List.maximumBy? You aren't even using areaMax, so instead it could just be maximumBy (comparing area), with Data.Ord.comparing. Commented Mar 31, 2015 at 18:35
  • I can not use the function maximumBy because I have to use only high-order functions; thanks a lot, I will try to fix it now. Commented Mar 31, 2015 at 18:58
  • 7
    @MassimilianoMartella maximumBy is a higher-order function because it takes a function (how to compare the items) as an input. Commented Mar 31, 2015 at 19:16

1 Answer 1

1

The problem is the ... then shape else (shape:list).

Every function has a return type. So does the lambda function.

The lambda needs to be of type a -> b. When you create an if expression it must yield a value from exactly one type. ( in this example b )

\shape currmax -> if ((area shape) > (area currmax))
                   then shape         -- this has type Shape
                   else (shape:list)  -- this has type [Shape]

You always need to make sure that the types are correct (fortunately GHC will complain)

Also i dont really know what you are trying to do

  1. You pass in 0 as the starting value for the accumulator function but with (area currmax) you are trying to use it as a Shape (area :: Shape -> Int)
  2. The problem with then (shape:list) is, that you want to prepend shape to list, but list will never change as it is an immutable parameter and the function does not call itself recursively.

Don't lose hope and don't stop trying, you'll not regret to learn this style of programming and to use this beautiful language.

Maybe just try to use a different example, there are dozens available for folds (http://book.realworldhaskell.org/read/functional-programming.html#fp.foldl)

By the way, this is a great book and you should take a look at it http://book.realworldhaskell.org/read/

Happy learning!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.