Ad
  • Custom User Avatar

    It's a function using its single argument to create a new function, only to apply it to that same argument. You could rewrite it using do-notation as such:

    fun = do
      x <- head
      \xs -> toUpper x:tail xs -- or `(:) toUpper x . tail`
    

    I guess the tricky part is realizing that head will get applied to the same value that xs represents, similar to how in the IO monad, you always write to the same enivironment you read from, and thanks to monads, this all happens implicitly. I generally think of monads as computations that can be composed/sequenced within a specific environment that they can interface with, without explicit references, a kind of meta-argument given at the start of the computation, in this case just a simple String.

    As for the (. tail) . (:) . toUpper part, it might be helpful to think of function composition as any other binary operator. Composition is defined as:

    f . g = \x -> f (g x)
    

    So once it has an argument, it'll first get applied to function right of ., and its result gets applied to the function left of it. For simplicity, let's define cons = (:) and rewrite the partially applied (. tail) to (\f -> f . tail), then we can work out the following:

    (\f -> f . tail) . cons
     => \k -> (\f -> f . tail) (cons k)
     => \k -> cons k . tail
     => \k -> (\y -> cons k (tail y))
    -- let's compose that with `toUpper`
    (\k -> (\y -> cons k (tail y))) . toUpper
     => \x -> (\k -> (\y -> cons k (tail y))) (toUpper x)
     => \x -> (\y -> cons (toUpper x) (tail y))
    -- and thanks to currying
     => \x y -> cons (toUpper x) (tail y)
    

    So we have a function that capitalizes a Char, and "conses" it to the tail of a String, and because of (head >>=), the Char will materialize from the same String tail will get applied to, giving us an overly complicated yet succint way to capitalize the first letter of a word.

    I'm not sure why I actually wrote it like that though, if I were to redo it, I'd use:

    (:) <$> toUpper . head <*> tail
    

    Which does the exact same thing, but for different reasons and without monads.

  • Custom User Avatar
  • Custom User Avatar

    can you explain the (head >>= (. tail) . (:) . toUpper) part?