
On Tue, Jun 26, 2012 at 10:08:49PM +0200, Obscaenvs wrote:
Sorry if this is a less than stellar question.
The problem: Given a function f :: a -> a -> a -> b, make it work on a list instead: f `applyTo`[x,y,z] where [x,y,z] :: [a]. My stab at a general solution was ` applyTo f [] = error "no arg" applyTo f (x:xs) = go (f x) xs where go acc [] = acc go acc (y:[]) = acc y go acc (y:ys) = go (acc $ y) ys `
I thought this would work, functions being "first class citizens" but ghci complains: "Occurs check: cannot construct the infinite type: t1 = t0 -> t1 In the return type of a call of `acc' Probable cause: `acc' is applied to too many arguments In the expression: acc y In an equation for `go': go acc (y : []) = acc y"
The 'probable cause' isn't the real cause here, but something to do with the fact that it's impossible to accumulate functions in this way... Or am I just too tired too make it work? I can see that the type of `go` could be a problem, but is it insurmountable?
The type of `go` is exactly the problem. In particular, the type of acc's first parameter. In the third clause of go's definition, we can see that `acc` and (acc $ y) are both used as the first argument to go, hence they must have the same type. However, this is impossible -- if acc has type (t0 -> t1), then y must have type t0, and (acc $ y) has type t1, so it would have to be the case that t1 = t0 -> t1 -- hence the error message. It is not possible in Haskell to define `applyTo`.* I know this function gets used a lot in lisp/scheme, but Haskell style is different. If you explain the context in which you wanted this function, perhaps we can help you figure out a better way to structure things so it is not needed. -Brent * At least not without crazy type class hackery.