1
votes

Hello can someone explain to me this example from Real World Haskell of function composiiton:

data Doc = ToBeDefined deriving (Show) 

(<>) :: Doc -> Doc -> Doc
a <> b = undefined

series :: Char -> Char -> (a -> Doc) -> [a] -> Doc
series open close item = enclose open close
                         . fsep . punctuate (char ',') . map item
                         -- Who does fsep compose with?

enclose :: Char -> Char -> Doc -> Doc
enclose begin end input = char begin <> input <> char <> end

I do not understand how who is the right operand of the . fsep expression.

( . ) [who is here ]  fsep 

Because from the looks of it close and open are just a characters.Can you compose a function with a data type (in our case a character)?

P.S Is it possible to curry the function composition?

so enclose accepts 3 parameters: 2 of them are already fixed open and close and the third one is the result of fsep.

Basically you can do f(x1...xn-1 xn) . g(y1....yn)(k) as long as g(y1...yn)(k)=xn .

1
That's actually the left operand.Willem Van Onsem
. is just like any other operator. f . g == (.) f g, and you can define sections like (f .) and (. g).chepner
What do you mean by "is it possible to curry the function composition" ?chi
I thought that given a function f and a function g they both must accept a parameter.In this case its more like f accepts 3 parameters ,of which 2 are already fixed and 1 is taken from g x - where x is the third parameter.Bercovici Adrian
(to your question's last sentence:) no, you can do ( f(x1...xn-1) . g(y1...yn) ) (k) as long as g(y1...yn)(k) = xn. ---- also, it probably should have been enclose begin end input = char begin <> input <> char end.Will Ness

1 Answers

5
votes

There's nothing very exciting going on here. The function you quoted is just

series open close item = enclose open close . fsep . punctuate (char ',') . map item

with a line break after the enclose open close for readability (which changes nothing about how this is parsed). I.e. the operands to the . you asked about are enclose open close and fsep.

Here, enclose open close is a partial application of the enclose function:

enclose :: Char -> Char -> Doc -> Doc
enclose open   ::  Char -> Doc -> Doc
enclose open close   ::    Doc -> Doc

thus you're composing a Doc -> Doc function before a function that yields a Doc.


Actually that's technically not quite true: because . is right-associative, the right operand is actually everything to its right, i.e.

     (enclose open close) . (fsep . punctuate (char ',') . map item)

but due to f . (g . h) ≡ (f . g) . h this doesn't matter.