packages feed

free-functors-0.1: examples/FreeNum.hs

{-# LANGUAGE FlexibleInstances #-}
module FreeNum where

import Data.Functor.Free

import Control.Applicative

instance Num (Free Num a) where
  Free l + Free r = Free $ (+) <$> l <*> r
  Free l * Free r = Free $ (*) <$> l <*> r
  Free l - Free r = Free $ (-) <$> l <*> r
  negate (Free f) = Free $ negate <$> f
  abs (Free f)    = Free $ abs <$> f
  signum (Free f) = Free $ signum <$> f
  fromInteger i   = Free $ pure (fromInteger i)

x, y :: Free Num String
x = return "x"
y = return "y"

expr :: Free Num String
expr = 1 + x * (3 - y)

-- Monadic bind is variable substitution
subst :: Free Num String -> Free Num a
subst e = e >>= \v -> case v of 
  "x" -> 10
  _   -> 2

-- Closed expressions can be evaluated to any other instance of Num
result :: Int
result = convertClosed (subst expr)