FreeモナドでDSLを作って、後から実装を変える例
code:hs
-- DSLのInterfaceを定義
data CalcF a
= Add Int a
| Sub Int a
| Mul Int a
| Div Int a
deriving (Functor)
-- Freeモナドを作成
type Calc a = Free CalcF a
-- ヘルパー関数の用意
add, sub, mul, div' :: Int -> Calc ()
add x = liftF (Add x ())
sub x = liftF (Sub x ())
mul x = liftF (Mul x ())
div' x = liftF (Div x ())
-- DSLを使ってコードを書く
program :: Calc ()
program = do
add 10
sub 5
mul 2
div' 2
code:hs
-- 実装1: 四則演算の結果をIntで返す
interpret :: Calc a -> Int -> Int
interpret (Free (Add x next)) state = interpret next (state + x)
interpret (Free (Sub x next)) state = interpret next (state - x)
interpret (Free (Mul x next)) state = interpret next (state * x)
interpret (Free (Div x next)) state = interpret next (state div x)
interpret (Pure _) state = state
code:hs
-- 実装2: 四則演算の結果をStringで返す
interpretString :: Calc a -> Int -> String
interpretString (Free (Add x next)) state = interpretString next (state + x)
interpretString (Free (Sub x next)) state = interpretString next (state - x)
interpretString (Free (Mul x next)) state = interpretString next (state * x)
interpretString (Free (Div x next)) state = interpretString next (state div x)
interpretString (Pure _) state = show state
ヘルパー関数は、ヘルパー関数に過ぎず、本質は型を組み合わせて構造を作るとこ
あとは、その構造をどういう風に解釈するか