In this question, the author has written an implementation of de Morgan's laws in Haskell. I understand the implementations of notAandnotB
, and notAornotB
, but I'm struggling to understand the implementation of notAorB
which is:
notAorB :: (Either a b -> c) -> (a -> c, b -> c)
notAorB f = (f . Left, f . Right)
Could someone explain how the (f . Left, f . Right)
part works? I've seen the .
operator used before, but with three arguments, not two.
Thank you in advance.
Recall that the definition of the .
operator is (f . g) x = f (g x)
, i.e. f . g = \x -> f (g x)
(syntactically, it is a binary operator, it is just that Haskell’s syntax sugar permits the latter definition to be restated as the former). So, the definition you have can be rephrased as
notAorB f = ((\x -> f (Left x)), (\y -> f (Right y)))
(this can be done mechanically by Lambdabot on #haskell, tell him to @unpl ‹expr›
), or more verbosely
notAorB f = (lt, rt)
where lt x = f (Left x)
rt y = f (Right y)
As always, try writing down the types. If (.) :: ∀ s t u. (t -> u) -> (s -> t) -> s -> u
, f :: Either a b -> c
, Left :: ∀ p q. p -> Either p q
, then f . Left
or (.) f Left :: a -> c
, etc.