Yasutaka Higa
data Similar a = Single a | Similar a (Similar a)
double :: Int -> Similar Int
double x = Single (2 * x)
twicePlus :: Int -> Similar Int
twicePlus x = Similar (x + x) (double x)
instance Functor Similar where
fmap f (Single a) = Single (f a)
fmap f (Similar a s) = Similar (f a) (fmap f s)
Similar (Single (Similar 1 (Single 1)))
(Single (Single (Similar 1 (Single 1))))
mu :: (Similar (Similar a)) -> Similar a
mu (Single s) = s
mu (Similar s ss) = similar s (mu ss)
instance Monad Similar where
return = Single
(Single x) >>= f = f x
(Similar x s) >>= f = mu $ Similar (f x) (fmap f s)
same :: (Eq a) => Similar a -> a
same (Single x) = x
same (Similar x s) = if x == (same s) then x else (error "same")
value :: Similar a -> a
value (Single x) = x
value (Similar x s) = value s
*Main> return 100 >>= double >>= twicePlus
Similar 400 (Single 400)
*Main> return 100 >>= double >>= twicePlus >>= plusTwo
Similar 402 (Similar 800 (Similar 402 (Single 800)))
*Main> same $ return 100 >>= double >>= twicePlus >>= plusTwo
*** Exception: same
*Main> same $ return 100 >>= double >>= twicePlus
400
instance Applicative Similar where
pure = Single
(Single f) <*> s = fmap f s
(Similar f s) <*> ss = similar (fmap f ss) (s <*> ss)