Skip to content

Instantly share code, notes, and snippets.

@missingfaktor
Created October 6, 2011 09:08
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save missingfaktor/1266912 to your computer and use it in GitHub Desktop.
Save missingfaktor/1266912 to your computer and use it in GitHub Desktop.
-- A simple definition without using any fancy functions.
haskell>let ifMaybe pred value = if pred value then Just value else Nothing
haskell>:t ifMaybe
ifMaybe :: (a -> Bool) -> a -> Maybe a
haskell>ifMaybe (const True) 2
Just 2
haskell>ifMaybe (const False) 2
Nothing
-- Using functions from standard library.
haskell>let ifMaybe pred value = mfilter pred $ Just value
haskell>:t ifMaybe
ifMaybe :: (a -> Bool) -> a -> Maybe a
haskell>ifMaybe (const True) 2
Just 2
haskell>ifMaybe (const False) 2
Nothing
-- A point-free version that uses section of (.).
haskell>let ifMaybe = (. Just) . mfilter
haskell>:t ifMaybe
ifMaybe :: (a -> Bool) -> a -> Maybe a
haskell>ifMaybe (const True) 2
Just 2
haskell>ifMaybe (const False) 2
Nothing
-- Same thing written with (<.|) combinator.
haskell>let ifMaybe = mfilter <.| Just
haskell>:t ifMaybe
ifMaybe :: (a -> Bool) -> a -> Maybe a
haskell>ifMaybe (const True) 2
Just 2
haskell>ifMaybe (const False) 2
Nothing
haskell>
@igstan
Copy link

igstan commented Oct 6, 2011

Ok, I see now. So, I don't think |.> and <.| are dual (you didn't say this though). Here's some ASCII art to describe the machinery:

What |.> does:

  a   b
  |   |
  \   /
    g
    |
    f
    |
 result

What <.| does:

  a   b
  |   |
  |   g
  |   |
  \   /
    f
    |
  result

The dual of <.| would be:

  a   b
  |   |
  g   |
  |   |
  \   /
    f
    |
  result

This looks a lot like Arrows, but I'm not sure I can express them in terms of those combinators. http://en.wikibooks.org/wiki/Haskell/Understanding_arrows

@missingfaktor
Copy link
Author

@igstan: Yes, you are right. |.> and <.|, as I defined them, are not duals of each other. Sorry if I unintentionally implied so in my tweets. And thanks for drawing these diagrams. They make things much more clear for me too. :-)

Here's what you get on applying lambdabot's @unpl command on these two combinators:

[15:16] <rahul> @unpl \f g -> (f .) . g
[15:16] <lambdabot> \ f g d i -> f (g d i)
[15:16] <rahul> @unpl \f g -> (. g) . f
[15:16] <lambdabot> \ f g d i -> f d (g i)

I am now trying to express these computations in terms of arrows. (With pen and paper) :-)

@missingfaktor
Copy link
Author

@igstan: Here is how far I managed to reach. :-)

(|*>) :: (b -> c) -> (a -> b1 -> b) -> (a, b1) -> c
f |*> g = f . uncurry g

(<*|) :: (a -> b -> c) -> (b1 -> b) -> (a, b1) -> c
f <*| g = uncurry f . second g

I changed the names of the functions because these require their arguments tupled. Can you help me make them take arguments in regular curried style?

@igstan
Copy link

igstan commented Oct 6, 2011

@missingfaktor: you can write them like this, but it's not really an improvement:

(|*>) :: (b -> c) -> (a -> b1 -> b) -> (a -> b1 -> c)
f |*> g = curry (f . uncurry g)

(<*|) :: (a -> b -> c) -> (b1 -> b) -> (a -> b1 -> c)
f <*| g = curry (uncurry f . second g)

@igstan
Copy link

igstan commented Oct 6, 2011 via email

@missingfaktor
Copy link
Author

With some help of @djinn and @pl commands of lambdabot...

Prelude Control.Arrow Control.Applicative> let regular = (. (,)) . (.)
Prelude Control.Arrow Control.Applicative> :t regular
regular :: ((a, b) -> c) -> a -> b -> c
Prelude Control.Arrow Control.Applicative> let f |.> g = regular $ f . uncurry g
Prelude Control.Arrow Control.Applicative> :t (|.>)
(|.>) :: (b1 -> c) -> (a -> b -> b1) -> a -> b -> c

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment