[Haskell-beginners] elegant handling of maybe and non-maybe values

Kyle Murphy orclev at gmail.com
Fri Sep 21 05:18:18 CEST 2012


I don't know if it's better, but there are a couple things that stick out to me.
First of all this:

--------
let (v', x) = case v of
                Nothing -> (Nothing, defaultValueOfX)
                Just vValue -> f vValue in
--------

Is encapsulated in the function maybe as in:

--------
let (v,' x) = maybe (Nothing, defaultValueOfX) f v
--------

I'm assuming in this case that v has type (Maybe a) and is the original input.
This sort of computation puts me in mind of the State monad though,
and I think the best solution
is going to involve it, or possibly Arrow.

-------
wrapWithState :: (a -> (Maybe a, b)) -> b -> State (Maybe a) b
wrapWithState f default = do
                                     v <- get
                                     let (v', x) = maybe (Nothing, default) f v
                                     put v'
                                     return x

x :: State (Maybe a) b
x = wrapWithState f defaultValueOfX
y :: State (Maybe a) b
y = wrapWithState g defaultValueOfY
z :: State (Maybe a) b
z = wrapWithState h defaultValueOfZ

getXYZ :: State (Maybe a) b
getXYZ = do
    x' <- x
    y' <- y
    z' <- z
    doSomethingWithXYZ x' y' z'

getV :: IO (a, v)
getV = do
   v <- whateverToGetV
   return $ runState getXYZ v
-------

That's really long and probably somewhat convoluted, plus I'd bet
there's a more elegant way
to do it with Applicative/Functor/Arrow, but I believe it should work.
Note that I use "b" as
the return type for all the state computations, but in practice they
could all return different types.

-R. Kyle Murphy
--
Curiosity was framed, Ignorance killed the cat.


On Thu, Sep 20, 2012 at 9:25 PM, Christopher Howard
<christopher.howard at frigidcode.com> wrote:
>
> I have a code situation similar to this simplified one: Let's say that
> I've got a value v that is a Maybe type, and values x, y, and z that are
> not. x, y, and z are dependent on the value inside v. So I must provide
> default values for x, y, and z. An additional complication is that every
> calculation returns a new (possibly different) value for v. So, I could
> do something like this:
>
> code:
> --------
> let (v', x) = case v of
>                 Nothing -> (Nothing, defaultValueOfX)
>                 Just vValue -> f vValue in
> let (v'', y) = case v' of
>                  Nothing -> (Nothing, defaultValueOfY)
>                  Just vValue -> g vValue in
> let (v''', z) = case v'' of
>                   Nothing -> (Nothing, defaultValueOfZ)
>                   Just vValue -> h vValue in
> --------
>
> (f, g, h represent the calculations I am performing.) In the end, I need
> the values of x, y, and z, and the last v value.
>
> Obviously, the above solution is not very elegant, especially if I add a
> few more variables. My other thought was some kind of fold operation,
> where I store the functions (calculations) and the default values in a
> list, and then fold over the list, applying subsequent values of v or
> returning default values, as appropriate. But this seems rather clunky,
> especially if I want to attach the values in the new list to variable
> names afterwards.
>
> Is there a better approach?
>
> --
> frigidcode.com
> indicium.us
>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>



More information about the Beginners mailing list