I've read two great series of articles about Autos and Free Monads and I'd like to combine this two techniques somehow.
I'd like to have something like:
data ProgramF a = Get (String -> a) | Set String a
instance Functor ProgramF where ...
type Program = Free ProgramF
get' :: Program String
get' = liftF $ Get id
set' :: String -> Program ()
set' s = liftF $ Set s ()
auto1 :: AutoM Program () String
auto1 = arrM \_ -> get'
auto2 :: AutoM Program String ()
auto2 = arrM \s -> set' s
auto3 :: AutoM Program () ()
auto3 = auto1 >>> auto2
...
But there are some problems, for example ArrowLoop
requires Program
to be an instance of MonadFix
which is not possible as far as I understand.
So my questions are:
- Are there ways to make
Auto
andFree
work together? - And if not, maybe there are other ways to achieve the goal?
Note: I'm pretty new to functional programming, so I understand from little to nothing in theory.
Update:
In one of the comments it was mentioned that Auto
is itself a form of fixpoint and I can use ProgramF
directly with it. So I guess that the type of Auto
should look something like this:
newtype Auto f a b = Auto (a -> f (b, (Auto f a b)))
But the problem now is that I can't figure out how to compose two Auto
s without f
being a Monad
.
My end goal is to have some composable pieces of code with internal state and a way to purify my code hiding all IO
effects (like log
or getLine
) in some kind of interpreter.
So I guess my real question is: how can I implement something described above?
Maybe I'm doing it all wrong and there is a better way. Can someone please give a simple example or provide some links to something similar?