Open snowleopard opened 8 years ago
As soon as I started on a test implementation I realised that we actually need isomorphism between the original type of signals and the wrapper interface. Indeed, if we only have a one-way mapping a -> b
then we can map two two previously distinct signals into one, which would be a mess. Haskell spots this and doesn't allow me to implement a Functor instance :)
So, the right direction seems to be towards an Iso
typeclass, and while we are at it, why not give a try to the revered Control.Lens
library: https://hackage.haskell.org/package/lens.
I've added a draft implementation for wrappers in #27:
wrap :: (a -> b) -> (b -> a) -> CircuitConcept a -> CircuitConcept b
wrap to from c = Concept
{
initial = wrapSpace $ initial c,
excited = \e -> wrapSpace $ excited c (fmap from e),
invariant = wrapSpace $ invariant c
}
where
wrapSpace p = \s -> p (State $ getState s . to)
My previous comment was somewhat misguided: I mixed up isomorphisms with invariant functors. The wrap
function actually implements the Invariant
class from Data.Functor.Invariant
.
Having said that, the input to the wrap
function is indeed an isomorphism: we need both to :: a -> b
as well as from :: b -> a
to wrap a circuit, which prevents us from smashing two different signals together, assuming that to . from = id
.
As discussed during today's Tuura meeting, we need a way to compose two concepts by matching some of their interface signals. As a simple example, consider connecting two buffers together in sequence:
How do we tell that we want to connect
b1
's outputB
tob2
's inputX
?A good solution seems to rely on wrappers:
An alert reader will spot that
wrap
is just anfmap
! Indeed, all we need to do is to write aFunctor
instance forCircuitConcept
, and then we will be able to wrap simply byfmap map21 b2
ormap21 <$> b2
using a fancy standard operator.I'll give this a try.