Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Semantic editor combinators #461

Open
masaeedu opened this issue Nov 23, 2017 · 2 comments
Open

Semantic editor combinators #461

masaeedu opened this issue Nov 23, 2017 · 2 comments

Comments

@masaeedu
Copy link
Member

masaeedu commented Nov 23, 2017

Conal Elliott has a pretty cool article on how just fmap and (generalized) flip are sufficient for doing complex transformations of functions of values of functions of ..., etc, simply by virtue of how many things are naturally functors of differing variance.

As an example, let's look at the signature for a foldl:

Prelude Data.Functor> :t foldl
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b

Let's say for whatever reason I wanted a slightly different foldl' that adds 2 to all of the as in that b -> a -> b expression, or something arbitrary like that.

Now I could sit down and start expending some mental effort to actually work out a transformation, but I could also just use Conal's totally mechanized, no-brain required approach. Given the original foldl, I want to take the argument's return's argument, and apply +2 to it. How do I express this with semantic editor combinators?

Prelude Data.Functor> arg = flip fmap
Prelude Data.Functor> ret = fmap
Prelude Data.Functor> foldl' = (arg . ret . arg) (+ 2) foldl
Prelude Data.Functor> foldl (+) 0 [1, 2, 3, 4]
10
Prelude Data.Functor> foldl' (+) 0 [1, 2, 3, 4]
18

I think a language of similar "semantic combinators" comprised of meaningful aliases could be useful in Sanctuary as well. The problem is that we don't have the convenient infix (.) operator, so our applications of S.map have to be on the left hand side. This makes things not nearly as convenient. I was hoping someone would be able to figure out an equivalent encoding in Sanctuary that is just as readable.

@masaeedu
Copy link
Member Author

masaeedu commented Nov 23, 2017

Another interesting example, motivated by recent discussion in the Gitter:

foldMap' f = ((arg . ret . arg) f foldl) mappend mempty

i.e. we can make a foldMap by simply editing foldl and applying the (Monoid a) => x -> a transformation to the second argument in the reducer, then applying away the reducer and seed with mappend and mempty.

@davidchambers
Copy link
Member

This is new to me, but I can at least provide the Sanctuary translation of the Haskell code:

const arg = S.flip (S.map);
const ret = S.map;
const reduce$ = S.pipe ([arg, ret, arg]) (S.add (2)) (S.reduce);

S.reduce (S.add) (0) ([1, 2, 3, 4]);  // => 10
reduce$ (S.add) (0) ([1, 2, 3, 4]);  // => 18

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants