Reputation: 1668
How can I find the type of a value in Haskell?
I want something like this:
data Vegetable =
Und Under
|Abv Above
is_vegetable ::a->Bool
is_vegetable a = if (a is of type Vegetable) then True else False
Update:
I want a datastructure to model the above tree.
I would also like to have some functions (is_drink, is_vegetable,is_wine,is_above) so that I can apply some filters on a list.
Upvotes: 2
Views: 1793
Reputation: 73748
You cannot do this in Haskell. All function arguments have concrete types (like Int
and String
) or they are type variables (like the a
in your example). Type variables can be restricted to belong to a certain type class.
When you use an unrestricted type variable, then you cannot do anything interesting with the values of that type. By restricting the type variable to a type class, you get more power: if you have Num a
, then you know that a
is a numeric type and so you can add, multiple, etc.
From your comment, it sounds like you need a (bigger) data type to hold the different types of elements in your tree. The Either a b
type may come in handy here. It is either Left a
or Right b
and so you can have a function like
is_vegetable :: Either Vegetable Drink -> Bool
is_vegetable (Left _) = True
is_vegetable (Right _) = False
Your tree nodes will then be Either Vegetable Dring
elements.
Upvotes: 9
Reputation: 213228
Tip for reading function signatures in Haskell:
f :: a -> Bool
This means f
takes one argument which could be anything, and f
does not have any information about the type. So it is impossible for f
to know if the argument is a Vegetable
. There are only three possible definitions for f
(two more for strict / non-strict variants, which I'm omitting for clarity):
-- version 1
f _ = True
-- version 2
f _ = False
-- version 3
f _ = undefined
You see f
is a very boring function because it is not allowed to know anything about its parameter. You could do something like this:
isVegetable :: Typeable a => a -> Bool
isVegetable x = case cast x :: Maybe Vegetable of
Just _ -> True
Nothing -> False
You would need to create an instance of Typeable
for Vegetable
,
data Vegetable = ... deriving Typeable
The signature f :: Typeable a => a -> Bool
means that f
has one parameter, and it does not know anything about that parameter except that the parameter has a type that is known at runtime.
Upvotes: 5
Reputation: 47042
You don't. You rely on the type system to ensure that the value is a Vegetable --- if the value is not a Vegetable, your program won't compile, much less run.
is_vegetable :: Vegetable -> Bool
is_vegetable _ = True -- so there is not much point to this function
Edit, upon seeing your comment:
data Foodstuff = Vegetable Vegetable
| Drink Drink
is_vegetable :: Foodstuff -> Bool
is_vegetable (Vegetable _) = True
is_vegetable _ = False
But this is still probably not what you want. Instead you probably want something like
case myFood of
Vegetable vegetable -> -- something involving `vegetable`
Drink drink -> -- something involving `drink`
Upvotes: 15