Description
Add support for an abstraction that combines a Functor and a Contravariant in a way similar to a Profunctor, but where the output parameter is constrained to the input parameter.
From Haskell:
class Invariant f where
invmap :: (a -> b) -> (b -> a) -> f a -> f b
This is a useful abstraction when dealing with bidirectional programming, for example:
type Decoder<'a> = (string -> Result<'a, string>)
type Encoder<'a> = ('a -> string)
type Codec<'a> =
{ decoder : Decoder<'a>
encoder : Encoder<'a> }
type Decoder<'a> with
static member Map(d : Decoder<'a>, f : 'a -> 'b) : Decoder<'b> = map f << d
type Encoder<'a> with
static member Contramap(e : Encoder<'a>, f : 'b -> 'a) : Decoder<'b> = f >> e
type Codec<'a> with
static member Invmap({ decoder = d; encoder = e } : Codec<'a>, f : 'a -> 'b, g : 'b -> 'a) : Codec<'b> =
{ decoder = map f d
encoder = contramap g e }
A similar related abstraction is an Invariant2, a sort of Bifunctor analog of Invariant
class Invariant2 f where
invmap2 :: (a -> c) -> (c -> a) -> (b -> d) -> (d -> b) -> f a b -> f c d
Which has a similar application, except that it allows the definition of types like Codec<'a, 'b>, where the encoded type is parametric in addition to the decoded type.
If you like the suggested additions, I would be happy to submit a PR with these abstractions added.
Description
Add support for an abstraction that combines a
Functorand aContravariantin a way similar to aProfunctor, but where the output parameter is constrained to the input parameter.From Haskell:
This is a useful abstraction when dealing with bidirectional programming, for example:
A similar related abstraction is an
Invariant2, a sort ofBifunctoranalog ofInvariantWhich has a similar application, except that it allows the definition of types like
Codec<'a, 'b>, where the encoded type is parametric in addition to the decoded type.If you like the suggested additions, I would be happy to submit a PR with these abstractions added.