5

I have the following simple code

import Data.String.Regex
import Data.Array

last <$> match someRegex "   1"

where

match someRegex "   1"

returns something like

Just ([Just ("   1"),Just ("   "),Just ("1")])

and

last <$> match someRegex "   1"

returns something like

Just (Just (Just ("   1"))) 

Now I have a deeply nested Maybe. Which makes it sort of hard to work with (even using functors). I have written myself a pair of helper functions - but I am sort of unhappy with that. It somehow doesn't feel right.

extract j = do
    case j of
        Nothing -> Nothing
        Just a -> a
extract2 jj = extract $ extract jj

And then using it like this

extract2 $ last <$> match someRegex "   1"

Is there a better/idiomatic way to do such things in Purescript/Haskell?

duplode
  • 33,731
  • 7
  • 79
  • 150
robkuz
  • 9,488
  • 5
  • 29
  • 50
  • 2
    If you don't want to join yet, but want to change it, remember that fmap is composable: `fmap . fmap :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b)`, `fmap . fmap . fmap :: (Functor f, Functor g, Functor h) => (a -> b) -> f (g (h a)) -> f (g (h b))` – Cubic Jul 27 '15 at 20:45
  • hmm my question was more if there is a way to avoid this nesting in the first place – robkuz Jul 27 '15 at 21:13
  • 1
    With `Maybe` there is little interesting information encoded in the multiple layers, but that might not be the case with other functors (e.g. you could use `fmap . fmap . fmap` to map over a doubly nested list while preserving all of its structure). – duplode Jul 27 '15 at 21:37

1 Answers1

11

Perhaps you're looking for the join function:

http://pursuit.purescript.org/packages/purescript-control/0.3.0/docs/Control.Bind#d:join

join collapses two layers of a structure down to a single layer, combining any effects. In the case of Maybe, that means that the resulting value will not be Nothing only if both layers were not Nothing.

Phil Freeman
  • 4,199
  • 1
  • 20
  • 15
  • so basically you are saying my `extract` function is some variant of `join` and that is the way things are being handled? duh! Isn't there a way (conceptually) to avoid that deeply nesting in the first place? – robkuz Jul 27 '15 at 21:12
  • 3
    One way is to notice that `join (map f x)` is the same as `x >>= f` by the `Monad` laws, so you could say `match someRegex " 1" >>= last` and save yourself a `join`. – Phil Freeman Jul 27 '15 at 21:22
  • `match` returns two layers of `Maybe` because of the multiple ways in which the JS version can fail, so at least one `join` is necessary if you care about everything being successful. – Phil Freeman Jul 27 '15 at 21:23