03-Multiply.purs

module Free.RunBased.Multiply where

import Prelude hiding (add)
import Effect (Effect)
import Effect.Console (log)
import Data.Functor.Variant (VariantF, on)
import Type.Row (type (+))
import Type.Proxy (Proxy(..))
import Free.RunBased.Value (value)
import Free.RunBased.Add (ADD, add, addAlgebra, eval)
import Run (Run, lift)

-- Data stuff
data MultiplyF e = MultiplyF e e

derive instance Functor MultiplyF

-- Variant Stuff
type MULTIPLY r = (multiply :: MultiplyF | r)

_multiply :: Proxy "multiply"
_multiply = Proxy

multiply :: forall r a
     . Run (MULTIPLY + r) a
    -> Run (MULTIPLY + r) a
    -> Run (MULTIPLY + r) a
multiply x y = join $ lift _multiply (MultiplyF x y)

example_multiply :: forall r. Run (MULTIPLY + r) Int
example_multiply = multiply (value 5) (value 6)

-- Eval stuff
multiplyAlgebra :: forall r
            . (VariantF r Int -> Int)
           -> (VariantF (MULTIPLY + r) Int -> Int)
multiplyAlgebra = on _multiply \(MultiplyF x y) -> x * y

amAlgebra :: forall r
           . (VariantF r Int -> Int)
          -> (VariantF (ADD + MULTIPLY + r) Int -> Int)
amAlgebra = addAlgebra >>> multiplyAlgebra

-- Examples
main :: Effect Unit
main = do
  log $ show $ eval multiplyAlgebra example_multiply
  log $ show $ eval amAlgebra (multiply (add (value 5) (multiply (value 2) (value 4))) (value 5))