04-Pattern-Matching-Using-Instance-Chains.purs

module Syntax.TypeLevel.Functions.PatternMatching.InstanceChains where

{-
So far, our type-level function's pattern matches use literal values.

Whenever we write...
   instance TL_Function InputValue1 OutputValue1
   instance TL_Function InputValue2 OutputValue2

... it's the equivalent of writing

   tl_Function :: Input -> Output
   tl_Function InputValue1 = OutputValue1
   tl_Function InputValue2 = OutputValue2

-}

-- Let's say we have the given value-level and type-level types/values:
data Fruit
  = Apple
  | Orange
  | Banana
  | Blueberry
  | Cherry

data ZeroOrOne = Zero | One

data FruitKind
foreign import data AppleK     :: FruitKind
foreign import data OrangeK    :: FruitKind
foreign import data BananaK    :: FruitKind
foreign import data BlueberryK :: FruitKind
foreign import data CherryK    :: FruitKind

data ZeroOrOneKind
foreign import data ZeroK :: ZeroOrOneKind
foreign import data OneK  :: ZeroOrOneKind

-- To write pattern matches with a 'catch-all' underscore binding

fruitToInt :: Fruit -> ZeroOrOne
fruitToInt Apple                    = Zero
fruitToInt _ {- Orange .. Cherry -} = One

-- we can use a feature called "Type Class Instance Chains:"

class FruitToInt :: FruitKind -> ZeroOrOneKind -> Constraint
class FruitToInt a i
  | a -> i                                                                {-

  Notice that we have omitted this type signature because
  we don't know what to do when we know `i` but not `a`

  , i -> a                                                                -}


instance FruitToInt AppleK ZeroK
else instance FruitToInt a OneK

{-
which is the same as writing...

  instance FruitToInt AppleK     ZeroK
  instance FruitToInt OrangeK    OneK
  instance FruitToInt BananaK    OneK
  instance FruitToInt BlueBerryK OneK
  instance FruitToInt CherryK     OneK
-}

{-
As of this writing, Purescript does not support all of the features
described in the paper below (i.e. backtracking), but it does work
for simpler use cases like above

Here's the related Purescript issue:
https://github.com/purescript/purescript/issues/2315

See the original paper here:
http://homepages.inf.ed.ac.uk/jmorri14/pubs/morris-icfp2010-instances.pdf
-}