0

While I was researching for a talk I came across something that I thought was not possible, and I still can't figure out why it is working. In the Control.Bind module, there is the definition of the fish operator:

composeKleisli ∷ ∀ a b c m. Bind m ⇒ (a → m b) → (b → m c) → a → m c

The documentation above it gives an example:

third = tail >=> tail >=> head

This is where my mind doesn't compute. I thought it would never compile* and yet it does:

> :t tail >=> tail >=> head
forall t2. Array t2 -> Maybe t2

How can this be? Clearly tail and head differ in the output m.

* or that the type checker would infer the following type: forall t2. Array (Array t2) -> Array t2

Regis Kuckaertz
  • 991
  • 5
  • 14

1 Answers1

3

So, m in that case is Maybe, hence you do not need to compose different type of monads.

More specifically:

tail :: forall a. Array a -> Maybe (Array a)
head :: forall a. Array a -> Maybe a

So

composeKliesli tail tail :: forall a. Array a → Maybe (Array a)
composeKliesli (composeKliesli tail tail) head :: forall a. Array a -> Maybe a

To see that you need to substitute m with Maybe and a, b and cs with either a or Array a in the type of composeKliesli.

mpetruska
  • 633
  • 3
  • 6