indigo-0.1.0.0: src/Indigo/Frontend/Program.hs
-- SPDX-FileCopyrightText: 2020 Tocqueville Group
--
-- SPDX-License-Identifier: LicenseRef-MIT-TQ
module Indigo.Frontend.Program
( IndigoM (..)
, Program (..)
, interpretProgram
) where
import Control.Monad (liftM)
import Prelude
import Indigo.Frontend.Statement
-- | This is freer monad (in other words operational monad).
--
-- It preserves the structure of the computation performed over it,
-- including @return@ and @bind@ operations.
-- This was introduced to be able to iterate over Indigo code and optimize/analyze it.
--
-- You can read a clearer description of this construction in
-- "The Book of Monads" by Alejandro Serrano.
-- There is a chapter about free monads, specifically about Freer you can read at page 259.
-- There is "operational" package which contains transformer of this monad and
-- auxiliary functions but it's not used because we are using only some basics of it.
data Program instr a where
Done :: a -> Program instr a
Instr :: instr a -> Program instr a
Bind :: Program instr a -> (a -> Program instr b) -> Program instr b
instance Functor (Program instr) where
fmap = liftM
instance Applicative (Program instr) where
pure = Done
(<*>) = ap
instance Monad (Program instr) where
return = pure
(>>=) = Bind
-- | Traverse over Freer structure and interpret it
interpretProgram
:: Monad m
=> (forall x . instr x -> m x)
-> Program instr a -> m a
interpretProgram _ (Done a) = return a
interpretProgram interp (Instr a) = interp a
interpretProgram interp (Bind instr rest) =
interpretProgram interp instr >>= (interpretProgram interp . rest)
-- | Monad for writing your contracts in.
newtype IndigoM a = IndigoM {unIndigoM :: Program (StatementF IndigoM) a}
deriving stock (Functor)
deriving newtype (Applicative, Monad)