views:

110

answers:

2

I have an assignment and am currently caught in one section of what I'm trying to do. Without going in to specific detail here is the basic layout: I'm given a data element, f, that holds four different types inside (each with their own purpose):

data F = F Float Int, Int

a function:

func :: F -> F-> Q  

Which takes two data elements and (by simple calculations) returns a type that is now an updated version of one of the types in the first f.

I now have an entire list of these elements and need to run the given function using one data element and return the type's value (not the data element). My first analysis was to use a foldl function:

myfunc :: F -> [F] -> Q
myfunc y [] = func y y -- func deals with the same data element calls
myfunc y (x:xs) = foldl func y (x:xs)

however I keep getting the same error:

"Couldn't match expected type 'F' against inferred type 'Q'. 
In the first argument of 'foldl', namely 'myfunc'
In the expression: foldl func y (x:xs)

I apologise for such an abstract analysis on my problem but could anyone give me an idea as to what I should do? Should I even use a fold function or is there recursion I'm not thinking about?

+3  A: 

The type of foldl is

foldl :: (a -> b -> a) -> a -> [b] -> a

but the type of func is

-- #      a -> b -> a
func  ::  F -> F -> Q

The type variable a cannot be simultaneously F and Q, thus the error.


If the Q can be converted to and from F, you could use

myfunc y xs = foldl (func . fromQ) (toQ y) xs

where

 func . fromQ :: Q -> F -> Q
        toQ y :: Q
           xs :: [F]

so this satisfies all the type requirements, and will return the final Q.

KennyTM
Thanks a lot for clearing up why foldl can't be used.Basically I have a list of F's that need to be updated. To do this I have to use the func function and go through the entire list and update the F's value as it goes through the list (then move to the next F). My answer was to simply get each data F (through a simple recursive call) then call myfunc with the F and the entire list of F's and return the value needed.
Snick
@Snick: but then you'll have a list of Q, not just a single Q.
KennyTM
I simply thought foldl would run the current F against the entire list using func, updating F as it went. I guess I'll have to go back to rethinking about a way to recursively call F with each element in the list with the new Q it acquires as it goes along
Snick
and now that I look at what I was asking foldl I realise how stupid I was being to try to do what I was doing
Snick
@Snick: You can't "update" F without returning it. Parameters are immutable in Haskell (unless you throw in the state or IO monads).
KennyTM
@KennyTM Wow I now see exactly where I was going wrong. Instead of being lazy thinking I could use foldl or something similar I rather used just a simple recursive function that returns each updated F. Thanks so much for pointing this out.
Snick
+2  A: 

maybe you need map?

map :: (f -> q) -> [f] -> [q]

it evaluates a function on each element in a list and gives a list of the results. I'm not sure why your function takes two Fs though, possibly to work with foldl?