#Dual Source

newtype Dual p s i o

Dual turns DualD into Invariant (it differs from Join).



#DualD Source

data DualD p s i o o'


  • DualD (p i o') (o -> s i)


#diverge Source

diverge :: forall i o o' p s. Functor (p i) => Profunctor p => (o' -> o) -> Dual p s i o -> DualD p s i o' o

#dual Source

dual :: forall i o p s. (p i o) -> (o -> s i) -> Dual p s i o

#dual' Source

dual' :: forall i p s. Applicative s => p i i -> Dual p s i i

#hoistParser Source

hoistParser :: forall i o p q s. ((p i) ~> (q i)) -> Dual p s i o -> Dual q s i o

#hoistSerializer Source

hoistSerializer :: forall i o p s s'. (s ~> s') -> Dual p s i o -> Dual p s' i o

#parser Source

parser :: forall i o p s. Dual p s i o -> p i o

#pureDual Source

pureDual :: forall i o p s. Applicative (p i) => Applicative s => Monoid i => o -> Dual p s i o

#serializer Source

serializer :: forall i o p s. Dual p s i o -> (o -> s i)

#(~) Source

Operator alias for Polyform.Dual.diverge (left-associative / precedence 5)

This function provides a way to diverge component serialization from parsing so we are able to "divide for a moment o type" and join them later by using Applicative composition. Lets use the same symbol as in codecs for similar operation.

Quick example:

profile = Dual $ ( { email1: , email2: , age: } <$> .email1 ~ emailDual <*> _.email2 ~ emailDual <*> _.age ~ ageDual)

So in the above example we can turn let say Dual p String Email into

DualD p String { email1: Email } Email

using _.email1 ~ emailDual and apply + Dual from above example "joins" these types again. Of course these two steps can be handled by some generic layer.