Reputation: 807
I am given a data type like the following
data Value = IntVal Integer |
BoolVal Bool
deriving Show
I am trying to write a function getVal
that takes a Value and returns the actual value inside. I was trying to achieve with pattern matching
getVal (IntVal val) = val
getVal (Bool bool) = bool
But Haskell complains about the returning types Couldn't match expected type 'Integer' with actuall type 'Bool'
So I gave it a signature returns a type variable
getVar :: Value -> a
But it won't work either
Upvotes: 3
Views: 1924
Reputation: 7599
Yes, this can be handled with help of type classes or GADTs or you can even use cast
leveraging Data.Typeable
. But all those thing are useful when you know Haskell well, and when you know what you're doing exactly.
In your case, you should really try to understand how Haskell works in general. Haskell is about imposing wise invariants that make it impossible to write “bad” programs (well, that's how I put it). This is done via type system, and without those invariants attached you cannot really do anything.
So now, you cannot do much with a thing of type a
, because you don't know much about it. If you want to return value from function that can be either Int
or Bool
(that's actually possible see existential quantification), you will be able to perform actions on that value that can be performed on Int
and on Bool
. You can get textual representation of that value for example.
Chances are you want more than that. In this case you probably shouldn't try to return Int
and Bool
at the same time without a way to understand what exactly you have as a result.
So, you can do the following for example:
getVar :: Value -> Either Int Bool
Or you can just dispatch:
case Value of
IntVal x -> doWhatYouWantToDoWithInteger x
BoolVal x -> doWhatYouWantToDoWithBoolean x
This is natural flow of Haskell. In every branch of program you now know what you're dealing with.
Hope it helps.
Upvotes: 10
Reputation: 17806
user3237465 and behzad.nouri have provided answers to your specific question. However I wonder if you are thinking by analogy with OO and dynamically typed languages. If you are taking "Value" as an argument to a function then you should use pattern matching to do the Right Thing with the value it holds. So suppose you are writing a function "showValue" to return the value as a string. I guess you are trying to do something like:
showValue :: Value -> String
showValue v = let v1 = getValue v in <something>
But that won't work in Haskell because the type system insists on knowing what type "v1" is. Instead you write it like this:
showValue (IntVal i) = "The Value is an integer " ++ show i
showValue (BoolVal b) = "The Value is a boolean " ++ show b
Upvotes: 2
Reputation: 12735
That's a job for GADT
s:
{-# LANGUAGE GADTs #-}
data Value a where
IntVal :: Integer -> Value Integer
BoolVal :: Bool -> Value Bool
getVal :: Value a -> a
getVal (IntVal i) = i
getVal (BoolVal b) = b
Upvotes: 3
Reputation: 78021
One way to do it is to use type-classes, to make a function polymorphic in return value:
\> :t getVal
getVal :: GetValue a => Value -> Maybe a
by a simple code as in bellow:
data Value = IntVal Integer
| BoolVal Bool
deriving Show
class GetValue a where
getVal :: Value -> Maybe a
instance GetValue Integer where
getVal (IntVal i) = Just i
getVal _ = Nothing
instance GetValue Bool where
getVal (BoolVal b) = Just b
getVal _ = Nothing
and let the type-inference decide the right function:
\> import Data.Maybe (fromJust)
\> (3 +) .fromJust . getVal $ IntVal 5 -- getVal :: Value -> Maybe Integer
8
\> not . fromJust . getVal $ BoolVal False -- getVal :: Value -> Maybe Bool
True
Upvotes: 4