0

So... I have written this to get 5 rectangles from user :

rectangles <- sequence . take 5 . cycle [getRect]

But it doesn't work. Then I have refactored it as this which is shorthand for writing braces:

rectangles <- sequence $ take 5 $ cycle [getRect]

I'm not sure why my function compostion is not valid. I would expect it to work like this if I'm to translate it to "real world" function, no? :

sequence(take(5 , cycle(getRect)))

[EDIT]

I understand that (.) is for function composition and $ for application but my composition should return function and than apply [getRect] to it. Should it not?

I'm looking at this from purely mathematical standpoint. Let's say that

cycle : a -> b
take 5 : b -> c  -- partially applied
sequence : c -> d

So why doesn't my composition work? It should be a function with argument [getRect] like this :

(sequence . take 5 . cycle)([getRect]) : a -> d

Where a is [getRect] and d is result of IO action.

Reygoch
  • 1,204
  • 1
  • 11
  • 24

1 Answers1

4

Function application binds more tightly than (.) so

sequence . take 5 . cycle [getRect]

is the same as

sequence . take 5 . (cycle [getRect])

since cycle [getRect] is list and not a function you get the error.

You can use parentheses to get the precedence you want:

rectangles <- (sequence . take 5 . cycle) [getRect]

note you could use replicateM instead:

rectangles <- replicateM 5 getRect
Lee
  • 142,018
  • 20
  • 234
  • 287
  • I think you have misunderstood me. Can you take a look at my question again? I didn't use (.) after cycle, I have put space to apply `[getRect]` to my composed function. – Reygoch Mar 15 '15 at 23:07
  • Now I have noticed I should probably wrap `take 5` in braces because it's supposed to return partially applied function and this way it takes `(.)` as second argument, but it still doesn't work. – Reygoch Mar 15 '15 at 23:09
  • 3
    @Reygoch - Function application binds more tightly than `(.)` so `take 5 . cycle [getRect]` is `take 5 . (cycle [getRect])` – Lee Mar 15 '15 at 23:15