2

Question

In the book Category Theory for Programmers by Bartosz Milewski, chapter 4.3.

You must code a Kleisli category where morphisms are partial functions. Here is my attempt which does not compile:

data Optional a = Valid a | Invalid deriving (Show)

return :: a -> Optional a
return x = Valid x

(>=>) :: (a -> Optional b) -> (b -> Optional c) -> (a -> Optional c)
f (>=>) g = \x ->
    let s = f x
    in | s == Valid v = g v
       | s == Invalid = Invalid

In the >=> operator definition, I want to pattern-match the intermediate value s to test if is Valid (and then call f) or if it is Invalid (and then return Invalid). How can I do this ?

vkubicki
  • 1,104
  • 1
  • 11
  • 26
  • 1
    I think first things first your should condiser making Optional type an instance of Monad type class and then the Kleisli composition operator would come free of charge `f >=> g = \x -> f x >>= g`. – Redu Dec 07 '19 at 14:42
  • 1
    I will try this later Redu, the point of the book is to gradually learn how to apply category theory. – vkubicki Dec 07 '19 at 14:44

1 Answers1

5

You can use case to do pattern matching:

f >=> g = \x ->
  case f x of
    Valid v -> g v
    Invalid -> Invalid

In your question you also seem to be trying to use guards for pattern matching and binding values. Haskell does not allow this. A guard is just a boolean valued expression which must be true for the preceding (sometimes optional) pattern to match. Haskell the language doesn’t really “understand” the (==) operator as meaning equality. It just sees it as a function like any other. And indeed one can define it for a type to not correspond to the same kind of equality that a pattern match requires.

A guard is allowed to use variables from the pattern (or from a larger scope) but can’t bind new ones like a pattern. Therefore this would be wrong because v would be undefined.

f >=> g = \x ->
  case f x of
    _ | x == Valid v -> g v
    _ | x == Invalid -> Invalid

It would also make it basically impossible for the compiler to ever know if your patterns are exhaustive (ie that there are no values which wouldn’t be matched by any case)

Dan Robertson
  • 4,315
  • 12
  • 17
  • 1
    In a sense, `case` is the fundamental tool of destructuring in Haskell, in that other pattern matching desugars into `case` statements in the core language. So it is good to get a handle on it. – Rein Henrichs Dec 07 '19 at 22:11
  • OK, so the guards is a syntax sugar in the particular situation where the case is applied to an argument of a function, right ? – vkubicki Dec 08 '19 at 14:34
  • @vkubicki I don’t understand what you mean. What do you think a guard is? What do you think it’s syntactic sugar for? – Dan Robertson Dec 08 '19 at 21:37
  • http://learnyouahaskell.com/syntax-in-functions there is section called guards – vkubicki Dec 08 '19 at 21:40
  • I thought that guards were used for pattern-matching, but it seems there are only used to perform tests on values. – vkubicki Dec 08 '19 at 21:50