tfausak / flow

:droplet: Write more understandable Haskell.
https://hackage.haskell.org/package/flow
MIT License
198 stars 10 forks source link

Add operators for fmap and friends #13

Closed bsima closed 7 years ago

bsima commented 7 years ago

Late-night haskell hacking has me thinking:

> :t ($)
($) :: (a -> b) -> a -> b
> :t (<|)
(<|) :: (a -> b) -> a -> b
> :t (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
> let (<<|) = fmap
> :t (<<|)
(<<|) :: Functor f => (a -> b) -> f a -> f b

My proposal is to add functions (<<|) and (|>>) which do the equivalent of (<|) and (|>) but over functors.

So the example here would go from:

(+) <$> Just 3 <*> Just 4

to:

(+) <<| Just 3 <*> Just 4

which IMHO shows the structure of the operation much better than the original. (Disclaimer: Haskell novice here, may have gotten some terminology wrong.)

bsima commented 7 years ago
> :t flip fmap
flip fmap :: Functor f => f a -> (a -> b) -> f b
> :t (|>)
(|>) :: a -> (a -> b) -> b

so I think (|>>) = flip fmap should work...

tfausak commented 7 years ago

Thanks for the suggestion! I've stuck with "plain" functions for now because it's not clear to stop. If (<$>) is (<<|) in Flow, what would (=<<) be, (<<<|)?

($)   ::              (a ->   b) ->   a ->   b
(<$>) :: Functor f => (a ->   b) -> f a -> f b
(=<<) :: Monad m   => (a -> m b) -> m a -> m b

Furthermore I generally avoid the applicative style and prefer do notation. ApplicativeDo makes this especially nice. I would write your example as:

do
  x <- Just 3
  y <- Just 4
  pure <| x + y -- or `pure (x + y)` or `pure $ x + y`
tfausak commented 7 years ago

I don't think I'll implement higher-order operators in Flow. If that's something you want, take a look at Data.Functor.Monadic.

infinity0 commented 4 years ago

FunctorMonadic wasn't as nice as I wanted it to be so I've gone ahead and uploaded https://hackage.haskell.org/package/op-0.1.0.0/docs/Control-Op.html