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

Higher order compose-s #462

Open
masaeedu opened this issue Nov 30, 2017 · 5 comments
Open

Higher order compose-s #462

masaeedu opened this issue Nov 30, 2017 · 5 comments

Comments

@masaeedu
Copy link
Member

It'd be nice to have some utilities to compose functions of 2, 3, etc. arguments with another that transforms the final argument. In Haskell, for example, you can have:

> import Data.Monoid
> import Data.Map

> compose2 = fmap . fmap
> :t compose2
compose2
  :: (Functor f1, Functor f) => (a -> b) -> f1 (f a) -> f1 (f b)

> -- Example usage

> :t mappend
mappend :: Monoid a => a -> a -> a

> :t singleton
singleton :: k -> a -> Map k a

> -- How to compose mappend after singleton?

> insert = compose2 mappend singleton
> :t insert
insert :: Ord k => k -> a -> Map k a -> Map k a

And so on for higher orders with compose3 = fmap . fmap . fmap for composing 3 argument functions etc.

@masaeedu masaeedu changed the title Higher order composes Higher order compose-s Nov 30, 2017
@safareli
Copy link
Member

safareli commented Dec 4, 2017

fmap for (a ->) type is compose right, so compose2 = (.) . (.)

@masaeedu
Copy link
Member Author

masaeedu commented Dec 4, 2017

@safareli Right, but if you can write it so it works with all functors instead of just functions, why not?

@gabejohnson
Copy link
Member

@masaeedu compose is a member of Semigroupoid so it works for more than just functions.

Can you give an example of how you would want to use compose2 with functors that aren't functions?

@masaeedu
Copy link
Member Author

masaeedu commented Dec 4, 2017

@gabejohnson Ah, I wasn't aware of that. I guess . satisfies multiple typeclasses. A compose<N> function as I have it up there simply fmaps over functors nested N levels deep. E.g. you can compose a String -> Int with an [String] to get an [Int], or compose2 a String -> Int with a [Map String String] to get [Map String Int].

Maybe it should be called map2 etc. in Sanctuary.

@davidchambers
Copy link
Member

The blackbird makes an appearance!

const compose2 = S.compose (S.compose) (S.compose);
const insert = compose2 (S.concat) (S.singleton);

insert ('z') (3) ({x: 1, y: 2});  // => {x: 1, y: 2, z: 3}

Defining S.compose2 and S.compose3 seems reasonable to me. Others may disagree. Feel free to submit a pull request, Asad. :)

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

4 participants