Hello,
I'm trying to write a lens for a datatype which seems easy in the Twan van Laarhoven encoding but I cannot find it as easy in the profunctorial one data Q5 a b = Q51 a (Identity b) | Q52 [b] lq5Twan :: Applicative f => (b -> f b') -> Q5 a b -> f (Q5 a b') lq5Twan f (Q51 a bs) = Q51 a <$> traverse f bs lq5Twan f (Q52 bs) = Q52 <$> traverse f bs data BT tt tt' b t t' a = BT1 (tt -> b) (t a) | BT2 (tt' -> b) (t' a) deriving (Functor,Foldable,Traversable) runBT (BT1 f x) = f x runBT (BT2 f x) = f x lq5Profunctor :: forall p a b b' . Traversing p => p b b' -> p (Q5 a b) (Q5 a b') lq5Profunctor = dimap pre post . second' . traverse' where pre (Q51 a x) = ((), BT1 (Q51 a) x) pre (Q52 bs) = ((), BT2 Q52 bs) post ((),x) = runBT x The issue here is that I need to project type 'b' into 2 different Traversable (sketched [] and Identity) so the traverse' must handle both together. Is the lq5Twan correct ? Which simpler ways to write the lq5Profunctor we have ? Thanks for help. paolino _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post. |
On Wed, May 02, 2018 at 03:07:05PM +0200, Paolino wrote:
> I'm trying to write a lens for a datatype which seems easy in the Twan van > Laarhoven encoding but I cannot find it as easy in the profunctorial one > > data Q5 a b = Q51 a (Identity b) | Q52 [b] > > lq5Twan :: Applicative f => (b -> f b') -> Q5 a b -> f (Q5 a b') > lq5Twan f (Q51 a bs) = Q51 a <$> traverse f bs > lq5Twan f (Q52 bs) = Q52 <$> traverse f bs [...] > lq5Profunctor :: forall p a b b' . Traversing p => p b b' -> p (Q5 a > b) (Q5 a b') [...] > Which simpler ways to write the lq5Profunctor we have ? Is `wander lq5Twan` good enough, or is your question more philosophical? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post. |
Well, I can accept it as an evidence of why not to use the profunctor encoding for multi target lens (if that's the name).
But I guess we are already in philosophy (so I'm more puzzled than before) and I hope you can elaborate more. .p 2018-05-02 18:10 GMT+02:00 Tom Ellis <[hidden email]>: On Wed, May 02, 2018 at 03:07:05PM +0200, Paolino wrote: _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post. |
In reply to this post by paolino
On Wed, May 02, 2018 at 03:07:05PM +0200, Paolino wrote:
> I'm trying to write a lens for a datatype which seems easy in the Twan van > Laarhoven encoding but I cannot find it as easy in the profunctorial one By the way ... which library are you using for profunctor lenses? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post. |
In reply to this post by paolino
I'm not sure what you mean. If you want to write a profunctor traversal
then `wander lq5Twan` seems fine. If you want to understand why it's hard to directly write profunctor traversals then I'm afraid I'm as puzzled as you. On Wed, May 02, 2018 at 06:29:09PM +0200, Paolino wrote: > Well, I can accept it as an evidence of why not to use the profunctor > encoding for multi target lens (if that's the name). > But I guess we are already in philosophy (so I'm more puzzled than before) > and I hope you can elaborate more. > > .p > > > 2018-05-02 18:10 GMT+02:00 Tom Ellis < > [hidden email]>: > > > On Wed, May 02, 2018 at 03:07:05PM +0200, Paolino wrote: > > > I'm trying to write a lens for a datatype which seems easy in the Twan > > van > > > Laarhoven encoding but I cannot find it as easy in the profunctorial one > > > > > > data Q5 a b = Q51 a (Identity b) | Q52 [b] > > > > > > lq5Twan :: Applicative f => (b -> f b') -> Q5 a b -> f (Q5 a b') > > > lq5Twan f (Q51 a bs) = Q51 a <$> traverse f bs > > > lq5Twan f (Q52 bs) = Q52 <$> traverse f bs > > [...] > > > lq5Profunctor :: forall p a b b' . Traversing p => p b b' -> p (Q5 a > > > b) (Q5 a b') > > [...] > > > Which simpler ways to write the lq5Profunctor we have ? > > > > Is `wander lq5Twan` good enough, or is your question more philosophical? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post. |
I'm not using any lens libraries, I'm writing both encodings from scratch based on standard libs, as a learning path. I see anyway that Traversing class is declaring exactly the Twan -> Profunctor promotion (given the Applicative on f) which looks a lot like a white flag on the "write traversal as profunctor" research. Actually I was induced from purescript to think that the profunctorial encoding was completely alternative to the twan, but I had no evidence of the fact, so I should better dig into purescript library. .p 2018-05-02 18:43 GMT+02:00 Tom Ellis <[hidden email]>: I'm not sure what you mean. If you want to write a profunctor traversal _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post. |
Here's a little gist I wrote.
See https://gist.github.com/phadej/04aae6cb98840ef9eeb592b76e6f3a67 for syntax highlighted versions. Hopefully it gives you some insights! \begin{code} {-# LANGUAGE RankNTypes, DeriveFunctor, DeriveFoldable, DeriveTraversable, TupleSections #-} import Data.Functor.Identity import Data.Profunctor import Data.Profunctor.Traversing import Data.Traversable import Data.Tuple (swap) data Q5 a b = Q51 a (Identity b) | Q52 [b] lq5Twan :: Applicative f => (b -> f b') -> Q5 a b -> f (Q5 a b') lq5Twan f (Q51 a bs) = Q51 a <$> traverse f bs lq5Twan f (Q52 bs) = Q52 <$> traverse f bs data BT tt tt' b t t' a = BT1 (tt -> b) (t a) | BT2 (tt' -> b) (t' a) deriving (Functor,Foldable,Traversable) runBT (BT1 f x) = f x runBT (BT2 f x) = f x lq5Profunctor :: forall p a b b' . Traversing p => p b b' -> p (Q5 a b) (Q5 a b') lq5Profunctor = dimap pre post . second' . traverse' where pre (Q51 a x) = ((), BT1 (Q51 a) x) pre (Q52 bs) = ((), BT2 Q52 bs) post ((),x) = runBT x \end{code} \begin{code} instance Functor (Q5 a) where fmap = fmapDefault instance Foldable (Q5 a) where foldMap = foldMapDefault instance Traversable (Q5 a) where traverse f (Q51 a bs) = Q51 a <$> traverse f bs traverse f (Q52 bs) = Q52 <$> traverse f bs lq5Twan' :: Applicative f => (b -> f b') -> Q5 a b -> f (Q5 a b') lq5Twan' = traverse lq5Profunctor' :: forall p a b b' . Traversing p => p b b' -> p (Q5 a b) (Q5 a b') lq5Profunctor' = traverse' \end{code} And in general: three steps: 1. create a Traversable newtype over your type 2. dimap pre post . traverse' 3. Profit! Compare that to writing Lens 1. bijection your 's' to (a, r) (Note: 'r' can be 's'!) 2. dimap to from . first' 3. Profit! Trivial examples: \begin{code} type Lens s t a b = forall p. Strong p => p a b -> p s t _1 :: Lens (a, c) (b, c) a b _1 = dimap id id . first' _2 :: Lens (c, a) (c, b) a b _2 = dimap swap swap . first' \end{code} Note again, that in usual `lens` definition we pick r to be s: we "carry over" the whole "s", though "s - a = r" would be enough. But in practice constructing "residual" is expensive. Think about record with 10 fields: residual in a single field lens would be 9-tuple - not really worth it. Interlude, one can define Traversal over first argument too. Using Bitraversable class that would be direct. In this case it's Affine (Traversal), so we can do "better" than using `traverse'`. \begin{code} lq5ProFirst :: forall p a a' b. (Choice p, Strong p) => p a a' -> p (Q5 a b) (Q5 a' b) lq5ProFirst = dimap f g . right' . first' where -- Think why we have chosen [b] + a * b -- compare to definition of Q5! -- -- The r + r' * s shape justifies the name Affine, btw. f :: Q5 a b -> Either [b] (a, Identity b) f (Q51 a x) = Right (a, x) f (Q52 bs) = Left bs g (Left bs) = Q52 bs g (Right (a, x)) = Q51 a x \end{code} Note: how the same 1. bijection to some structure (`r' + r * a` in this case 2. dimap to from . ... 3. Profit pattern is applied again. Another way to think about it is that we 1. Use `Iso` (for all Profunctor!) to massage value into the form, so 2. we can use "Optic specific" transform 3. Profit! And optic specific: - Lens -> Products - Prism -> Coproducts (Sums) - Traversal -> Traversable - Setter -> Functor (Mapping type class has map' :: Functor f => p a b -> p (f a) (f b)) - etc. So the fact that defining arbitrary Traversals directly is more handy with `wander`, than `traverse'` (as you can omit `dimap`!) is more related to the fact that we have \begin{spec} class Traversable t where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) \end{spec} ... and we (well, me) don't yet know another elegant way to capture "the essense of Traversable". (I don't think FunList is particularly "elegant") Sidenote: we can define Lens using Traversing/Mapping -like class too, hopefully it gives you another viewpoint too. \begin{code} class Functor t => Singular t where single :: Functor f => (a -> f b) -> t a -> f (t b) fmapSingle :: Singular t => (a -> b) -> t a -> t b fmapSingle ab ta = runIdentity (single (Identity . ab) ta) instance Singular Identity where single f (Identity a) = Identity <$> f a instance Singular ((,) a) where single f (a, b) = (a,) <$> f b class Profunctor p => Strong' p where single' :: Singular f => p a b -> p (f a) (f b) instance Strong' (->) where single' ab = fmap ab instance Functor f => Strong' (Star f) where single' (Star afb) = Star (single afb) -- lens using Strong' & Single: 1. 2. 3. lens' :: Strong' p => (s -> a) -> (s -> b -> t) -> p a b -> p s t lens' sa sbt = dimap (\s -> (s, sa s)) (\(s,b) -> sbt s b) . single' \end{code} Cheers, Oleg On 02.05.2018 20:09, Paolino wrote: > I'm not using any lens libraries, I'm writing both encodings from > scratch based on standard libs, as a learning path. > I see anyway that Traversing class is declaring exactly the Twan -> > Profunctor promotion (given the Applicative on f) which looks a lot > like a white flag on the "write traversal as profunctor" research. > Actually I was induced from purescript to think that the profunctorial > encoding was completely alternative to the twan, but I had no evidence > of the fact, so I should better dig into purescript library. > > .p > > 2018-05-02 18:43 GMT+02:00 Tom Ellis > <[hidden email] > <mailto:[hidden email]>>: > > I'm not sure what you mean. If you want to write a profunctor > traversal > then `wander lq5Twan` seems fine. If you want to understand why > it's hard > to directly write profunctor traversals then I'm afraid I'm as > puzzled as > you. > > On Wed, May 02, 2018 at 06:29:09PM +0200, Paolino wrote: > > Well, I can accept it as an evidence of why not to use the > profunctor > > encoding for multi target lens (if that's the name). > > But I guess we are already in philosophy (so I'm more puzzled > than before) > > and I hope you can elaborate more. > > > > .p > > > > > > 2018-05-02 18:10 GMT+02:00 Tom Ellis < > > [hidden email] > <mailto:[hidden email]>>: > > > > > On Wed, May 02, 2018 at 03:07:05PM +0200, Paolino wrote: > > > > I'm trying to write a lens for a datatype which seems easy > in the Twan > > > van > > > > Laarhoven encoding but I cannot find it as easy in the > profunctorial one > > > > > > > > data Q5 a b = Q51 a (Identity b) | Q52 [b] > > > > > > > > lq5Twan :: Applicative f => (b -> f b') -> Q5 a b -> f (Q5 a b') > > > > lq5Twan f (Q51 a bs) = Q51 a <$> traverse f bs > > > > lq5Twan f (Q52 bs) = Q52 <$> traverse f bs > > > [...] > > > > lq5Profunctor :: forall p a b b' . Traversing p => p b b' -> > p (Q5 a > > > > b) (Q5 a b') > > > [...] > > > > Which simpler ways to write the lq5Profunctor we have ? > > > > > > Is `wander lq5Twan` good enough, or is your question more > philosophical? > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > <http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe> > Only members subscribed via the mailman list are allowed to post. > > > > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post. signature.asc (849 bytes) Download Attachment |
Hi Oleg, How easy should it be to "create a Traversable newtype over your type" ? data Q6 a b c = Q61 a (Identity b) | Q62 [b] | Q63 c newtype Q6b a c b = Q61b (Q6 a b c) I cannot automatically derive anything for Q6b (Functor, Foldable, Traversable). So we are back to hand writing lenses for Q6, or I miss something ? For the rest, it was a very nice followup, I'm still rereading. Thanks Best .p 2018-05-02 23:06 GMT+02:00 Oleg Grenrus <[hidden email]>: Here's a little gist I wrote. _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post. |
Hi Paolino,
sorry for not replying promptly. Your type Q6 is Bitraversable which is in already in the base library (actually Triversable, if there were such class), should GHC be able to derive it? What else GHC should be able to derive? To my understanding (unfortunately I forgot the details), is that we'd would like to be able to teach GHC to derive instances from libraries, so we don't end up wiring special code for all instances out there. Also we'd might want different strategies for some type-classes (Bi/Traversable instances are unique, so that concern doesn't apply here). There's a GHC ticket for it [1], there are technical difficulties to overcome (and there is TH, more below), so there weren't much progress. That said, for Bitraversable, you could use `Data.Bifunctor.TH` [2], then you can use `bitraverse f pure` (sans wrapping/unwrapping) for Q6 to implement `traverse f` of Q6b. - Oleg [1]: https://ghc.haskell.org/trac/ghc/ticket/12457 [2]: http://hackage.haskell.org/package/bifunctors-5.5.2/docs/Data-Bifunctor-TH.html On 03.05.2018 15:54, Paolino wrote: > Hi Oleg, > > How easy should it be to "create a Traversable newtype over your type" ? > > data Q6 a b c = Q61 a (Identity b) | Q62 [b] | Q63 c > > newtype Q6b a c b = Q61b (Q6 a b c) > > I cannot automatically derive anything for Q6b (Functor, Foldable, > Traversable). > So we are back to hand writing lenses for Q6, or I miss something ? > > For the rest, it was a very nice followup, I'm still rereading. > > Thanks > > Best > > .p > > > > > 2018-05-02 23:06 GMT+02:00 Oleg Grenrus <[hidden email] > <mailto:[hidden email]>>: > > Here's a little gist I wrote. > > See > https://gist.github.com/phadej/04aae6cb98840ef9eeb592b76e6f3a67 > <https://gist.github.com/phadej/04aae6cb98840ef9eeb592b76e6f3a67> > for syntax highlighted versions. > > Hopefully it gives you some insights! > > \begin{code} > {-# LANGUAGE RankNTypes, DeriveFunctor, DeriveFoldable, > DeriveTraversable, TupleSections #-} > import Data.Functor.Identity > import Data.Profunctor > import Data.Profunctor.Traversing > import Data.Traversable > import Data.Tuple (swap) > > data Q5 a b = Q51 a (Identity b) | Q52 [b] > > lq5Twan :: Applicative f => (b -> f b') -> Q5 a b -> f (Q5 a b') > lq5Twan f (Q51 a bs) = Q51 a <$> traverse f bs > lq5Twan f (Q52 bs) = Q52 <$> traverse f bs > > data BT tt tt' b t t' a = BT1 (tt -> b) (t a) | BT2 (tt' -> b) (t' a) > deriving (Functor,Foldable,Traversable) > runBT (BT1 f x) = f x > runBT (BT2 f x) = f x > > lq5Profunctor :: forall p a b b' . Traversing p => p b b' -> p (Q5 > a b) > (Q5 a b') > lq5Profunctor = dimap pre post . second' . traverse' where > pre (Q51 a x) = ((), BT1 (Q51 a) x) > pre (Q52 bs) = ((), BT2 Q52 bs) > post ((),x) = runBT x > \end{code} > > \begin{code} > instance Functor (Q5 a) where fmap = fmapDefault > instance Foldable (Q5 a) where foldMap = foldMapDefault > instance Traversable (Q5 a) where > traverse f (Q51 a bs) = Q51 a <$> traverse f bs > traverse f (Q52 bs) = Q52 <$> traverse f bs > > lq5Twan' :: Applicative f => (b -> f b') -> Q5 a b -> f (Q5 a b') > lq5Twan' = traverse > > lq5Profunctor' :: forall p a b b' . Traversing p => p b b' -> p > (Q5 a b) > (Q5 a b') > lq5Profunctor' = traverse' > \end{code} > > And in general: three steps: > > 1. create a Traversable newtype over your type > 2. dimap pre post . traverse' > 3. Profit! > > Compare that to writing Lens > > 1. bijection your 's' to (a, r) (Note: 'r' can be 's'!) > 2. dimap to from . first' > 3. Profit! > > Trivial examples: > > \begin{code} > type Lens s t a b = forall p. Strong p => p a b -> p s t > > _1 :: Lens (a, c) (b, c) a b > _1 = dimap id id . first' > > _2 :: Lens (c, a) (c, b) a b > _2 = dimap swap swap . first' > \end{code} > > Note again, that in usual `lens` definition we pick r to be s: > we "carry over" the whole "s", though "s - a = r" would be enough. > But in practice constructing "residual" is expensive. > Think about record with 10 fields: residual in a single field lens > would be 9-tuple - not really worth it. > > Interlude, one can define Traversal over first argument too. > Using Bitraversable class that would be direct. > > In this case it's Affine (Traversal), so we can do "better" than using > `traverse'`. > > \begin{code} > lq5ProFirst :: forall p a a' b. (Choice p, Strong p) => p a a' -> > p (Q5 > a b) (Q5 a' b) > lq5ProFirst = dimap f g . right' . first' where > -- Think why we have chosen [b] + a * b > -- compare to definition of Q5! > -- > -- The r + r' * s shape justifies the name Affine, btw. > f :: Q5 a b -> Either [b] (a, Identity b) > f (Q51 a x) = Right (a, x) > f (Q52 bs) = Left bs > > g (Left bs) = Q52 bs > g (Right (a, x)) = Q51 a x > \end{code} > > Note: how the same > > 1. bijection to some structure (`r' + r * a` in this case > 2. dimap to from . ... > 3. Profit > > pattern is applied again. > > Another way to think about it is that we > > 1. Use `Iso` (for all Profunctor!) to massage value into the form, so > 2. we can use "Optic specific" transform > 3. Profit! > > And optic specific: > - Lens -> Products > - Prism -> Coproducts (Sums) > - Traversal -> Traversable > - Setter -> Functor (Mapping type class has map' :: Functor f => p a b > -> p (f a) (f b)) > - etc. > > So the fact that defining arbitrary Traversals directly is more > handy with > `wander`, than `traverse'` (as you can omit `dimap`!) is more > related to the > fact that we have > > \begin{spec} > class Traversable t where > traverse :: Applicative f => (a -> f b) -> t a -> f (t b) > \end{spec} > > ... and we (well, me) don't yet know another elegant way to > capture "the > essense of Traversable". (I don't think FunList is particularly > "elegant") > > > Sidenote: we can define Lens using Traversing/Mapping -like class too, > hopefully it gives you another viewpoint too. > > \begin{code} > class Functor t => Singular t where > single :: Functor f => (a -> f b) -> t a -> f (t b) > > fmapSingle :: Singular t => (a -> b) -> t a -> t b > fmapSingle ab ta = runIdentity (single (Identity . ab) ta) > > instance Singular Identity where > single f (Identity a) = Identity <$> f a > > instance Singular ((,) a) where > single f (a, b) = (a,) <$> f b > > class Profunctor p => Strong' p where > single' :: Singular f => p a b -> p (f a) (f b) > > instance Strong' (->) where > single' ab = fmap ab > > instance Functor f => Strong' (Star f) where > single' (Star afb) = Star (single afb) > > -- lens using Strong' & Single: 1. 2. 3. > lens' :: Strong' p => (s -> a) -> (s -> b -> t) -> p a b -> p s t > lens' sa sbt = dimap (\s -> (s, sa s)) (\(s,b) -> sbt s b) . single' > \end{code} > > Cheers, Oleg > > > On 02.05.2018 20:09, Paolino wrote: > > I'm not using any lens libraries, I'm writing both encodings from > > scratch based on standard libs, as a learning path. > > I see anyway that Traversing class is declaring exactly the Twan -> > > Profunctor promotion (given the Applicative on f) which looks a > lot > > like a white flag on the "write traversal as profunctor" research. > > Actually I was induced from purescript to think that the > profunctorial > > encoding was completely alternative to the twan, but I had no > evidence > > of the fact, so I should better dig into purescript library. > > > > .p > > > > 2018-05-02 18:43 GMT+02:00 Tom Ellis > > <[hidden email] > <mailto:[hidden email]> > > <mailto:[hidden email] > <mailto:[hidden email]>>>: > > > > I'm not sure what you mean. If you want to write a profunctor > > traversal > > then `wander lq5Twan` seems fine. If you want to understand why > > it's hard > > to directly write profunctor traversals then I'm afraid I'm as > > puzzled as > > you. > > > > On Wed, May 02, 2018 at 06:29:09PM +0200, Paolino wrote: > > > Well, I can accept it as an evidence of why not to use the > > profunctor > > > encoding for multi target lens (if that's the name). > > > But I guess we are already in philosophy (so I'm more puzzled > > than before) > > > and I hope you can elaborate more. > > > > > > .p > > > > > > > > > 2018-05-02 18:10 GMT+02:00 Tom Ellis < > > > [hidden email] > <mailto:[hidden email]> > > <mailto:[hidden email] > <mailto:[hidden email]>>>: > > > > > > > On Wed, May 02, 2018 at 03:07:05PM +0200, Paolino wrote: > > > > > I'm trying to write a lens for a datatype which seems easy > > in the Twan > > > > van > > > > > Laarhoven encoding but I cannot find it as easy in the > > profunctorial one > > > > > > > > > > data Q5 a b = Q51 a (Identity b) | Q52 [b] > > > > > > > > > > lq5Twan :: Applicative f => (b -> f b') -> Q5 a b -> f > (Q5 a b') > > > > > lq5Twan f (Q51 a bs) = Q51 a <$> traverse f bs > > > > > lq5Twan f (Q52 bs) = Q52 <$> traverse f bs > > > > [...] > > > > > lq5Profunctor :: forall p a b b' . Traversing p => p b > b' -> > > p (Q5 a > > > > > b) (Q5 a b') > > > > [...] > > > > > Which simpler ways to write the lq5Profunctor we have ? > > > > > > > > Is `wander lq5Twan` good enough, or is your question more > > philosophical? > > > > _______________________________________________ > > Haskell-Cafe mailing list > > To (un)subscribe, modify options or view archives go to: > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > <http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe> > > > <http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > <http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe>> > > Only members subscribed via the mailman list are allowed to > post. > > > > > > > > > > _______________________________________________ > > Haskell-Cafe mailing list > > To (un)subscribe, modify options or view archives go to: > > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > <http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe> > > Only members subscribed via the mailman list are allowed to post. > > > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > <http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe> > Only members subscribed via the mailman list are allowed to post. > > _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post. signature.asc (849 bytes) Download Attachment |
Free forum by Nabble | Edit this page |