Tue Jul 24 18:21:49 EDT 2018
Upside-down : the dual implementation in terms of type families
EDIT: Not so sure any more...
Turning it upside down, maybe.
Can this be done by representing the idea of a sequence as an
applicative functor of a generic data type?
But how to perform feedback?
This requires explicit implementation of "delay".
Let's try that out.
class Functor t => Delay (F t) where
delay :: F t -> F t
instance Delay  where
delay (a:as) = as
Then, using type families, it might be possible to write alternative
implementations that generate code.
I'm still not comfortable using circular programming, so I'm inclined
to use a "close" operator. Essentially it is something that turns a
pure function into a sequence.
But just for the fun of it, can it be done to use delay?
I don't see it and it really complicates things.
The proper way is to make "close" explicit.
module Causal where
class Functor f => Causal f where
close :: (a -> (a, b)) -> a -> f b
instance Causal  where
close :: u s0 = (o:os) where
(s, o) = u s0
os = u s
integral = close $ \s -> (s + 1, s)
But this is just unfold.
No. It is special in that what it is unfolded into is not necessarily a list.
I think this is going to work.. The key phrase in last week's reading
was that type families are sort of dual to type classes.
EDIT: Some inspection is needed to fish out the input value, so close
is not enough.
closei :: (s -> i -> (s, o)) -> s -> f i -> f o
It surprised me before that I could write this as applicative, but I
think that used a representation of singals as (s->(s,o).
Actually that still works here, but requires that particular
constraint on the representation. We don't need that. We just need
close over i/o and state.
Ok I think I got it:
Seq.erl defines Seq A composition of m and r
SeqApp.erl exports primitives lifted to that representation.
A "close" Causal class is implemented for each of the m.r compositions.
The work here is in the individual implementations.
I don't think that type families are needed. The behavior is in the functor.
And it is important to compose m and r!
So the insight is that these should be functors.
That is not trivial in itself.
And actually, doesn't work in general.
Nope.... m is the functor.
So this whole thing doesn't work because there are no pure r S
function, so close doesn't make sense.
So the "f" cannot be the M of the implementation. The wrapping needs
to be doubled-up:
F (M (R S))
So it looks like this just doesn't work in the current setting.
Something else is needed.
Deleting it. There is no point..