I have the following data type and example equation that I want to transform with a futumorphism...
import Matryoshka as M
import Data.Functor.Nu (Nu(..), observe, unfold)
data ArithmeticF a
= Mult a a
| Div a a
| Add a a
| Num Number
type Arithmetic = Nu ArithmeticF
derive instance functorArith :: Functor ArithmeticF
equation :: Arithmetic
equation = (div (n 3.0) (n 4.0)) `add` (div (n 3.0) (n 4.0))
mult :: Arithmetic -> Arithmetic -> Arithmetic
mult a b = M.embed $ Mult a b
div :: Arithmetic -> Arithmetic -> Arithmetic
div a b = M.embed $ Div a b
add :: Arithmetic -> Arithmetic -> Arithmetic
add a b = M.embed $ Add a b
n :: Number -> Arithmetic
n a = M.embed $ Num a
Using futu
this is my attempt at writing a function to factor out (Div (Num 1.0) (Num 4.0))
from the equation.
In the end I want the resulting tree to be (Mult (Div (Num 1.0) (Num 4.0)) (Add (Num 3.0) (Num 3.0)))
.
This function type checks but I must be doing something wrong, since it doesn't evaluate when I run it.
solve :: Arithmetic -> Number
solve = M.cata algebra
simplify :: Arithmetic -> Arithmetic
simplify s = M.futu factor s
factor :: GCoalgebra (Free ArithmeticF) ArithmeticF Arithmetic
factor s = case M.project s of
(Add a b) ->
case (Tuple (M.project a) (M.project b)) of
(Tuple (Div c d) (Div e f)) -> do
let dd = solve d
let ff = solve f
if dd == ff
then
Mult
(liftF $ observe (unfold dd (\m -> Div 1.0 dd )))
(liftF $ observe (unfold c (\g -> Add c e )))
else Add (liftF $ observe a) (liftF $ observe b)
_ -> Add (liftF $ observe a) (liftF $ observe b)
(Div a b) -> Div (liftF $ observe a) (liftF $ observe b)
(Mult a b) -> Mult (liftF $ observe a) (liftF $ observe b)
(Num a) -> (Num a)
main = log $ M.cata show (simplify equation)