elegant handling of maybe and non-maybe values
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
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@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@haskell.org http://www.haskell.org/mailman/listinfo/beginners
On Fri, Sep 21, 2012 at 8:25 AM, Christopher Howard < christopher.howard@frigidcode.com> wrote:
But this seems rather clunky, especially if I want to attach the values in the new list to variable names afterwards.
Agreed. Haskell is not Lisp, so there's no attachment (TH notwithstanding) to variable names ['a'..'z'] if that's what you're thinking. Could you provide the concrete scenario of what you're trying to achieve? -- Kim-Ee On Fri, Sep 21, 2012 at 8:25 AM, Christopher Howard < christopher.howard@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@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (3)
-
Christopher Howard -
Kim-Ee Yeoh -
Kyle Murphy