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))
F t

So it looks like this just doesn't work in the current setting.
Something else is needed.

Deleting it.  There is no point..