Corovei Andrei
Corovei Andrei

Reputation: 1668

Haskell type of

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. enter image description here

Upvotes: 2

Views: 1793

Answers (3)

Martin Geisler
Martin Geisler

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

Dietrich Epp
Dietrich Epp

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

dave4420
dave4420

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

Related Questions