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

filterM incompatible with haskell #87

Open
danr opened this issue Feb 17, 2018 · 1 comment
Open

filterM incompatible with haskell #87

danr opened this issue Feb 17, 2018 · 1 comment

Comments

@danr
Copy link

danr commented Feb 17, 2018

The filterM in this library has this type

filterM :: (Alternative m, Monad m) => (a -> Boolean, m a) -> m a

whereas filterM in Haskell is (reframed slighly):

filterM :: (Monad m, Traversable f) => (a -> m Boolean, f a) -> f a

The important part is that the predicate returns inside the monad. This allows for example succinct implementation of powerset:

powerset :: [a] -> [[a]]
powerset = filterM (const [False, True])

as well as enabling logging/state/etc inside the predicate:

countingFilterM :: (a -> Bool) -> [a] -> State Int [a]
countingFilterM p = filterM (\ x -> modify succ >> return (p x))

Please consider exporting filterM to have the same functionality as in Haskell's Control.Monad.

@davidchambers
Copy link
Member

Thanks very much for raising this issue, @danr. :)

Until recently Fantasy Land did not define a Filterable type class, so it was necessary to cobble together a filter function from the type classes available at the time. In #2 we introduced two filter functions:

filter :: (Applicative f, Foldable f, Monoid (f a)) => (a -> Boolean, f a) -> f a
filterM :: (Monad m, Monoid (m a)) => (a -> Boolean, m a) -> m a

The goal was to support as many filterable types as possible by providing two different derivations. The functions were necessarily given different names, with the M suffix hinting at the Monad m constraint. Although the M suffix may have been added for the same reason as in Haskell, Sanctuary's filterM was never intended to mirror its Haskell namesake.

In #37 the type of filterM was changed to permit Z.filterM(odd, Just(4)):

-filterM :: (Monad m, Monoid (m a)) => (a -> Boolean, m a) -> m a
+filterM :: (Alternative m, Monad m) => (a -> Boolean, m a) -> m a

Recently, in #80, the two filter functions were replaced with a single unified function:

filter :: Filterable f => (a -> Boolean, f a) -> f a

Now that the name is available we could provide the Sanctuary equivalent of Haskell's filterM. I find your powerset example extremely compelling! If you're interested in working on a pull request for this addition, please say so. :)

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