Reputation: 49
Could you please show me how can I check if type of func
is Tree
or not, in code not in command page?
data Tree = Leaf Float | Gate [Char] Tree Tree deriving (Show, Eq, Ord)
func a = Leaf a
Upvotes: 0
Views: 2545
Reputation: 1741
Here's how to determine what the type of a binding is in Haskell: take something like f a1 a2 a3 ... an = someExpression
and turn it into f = \a1 -> \a2 -> \a3 -> ... \an -> someExpression
. Then find the type of the expression on the right hand side.
To find the type of an expression, simply add a SomeType ->
for each lambda, where SomeType
is whatever the appropriate type of the bound variable is. Then use the known types in the remaining (lambda-less) expression to find its actual type.
For your example: func a = Leaf a
turns into func = \a -> Leaf a
. Now to find the type of \a -> Leaf a
, we add a SomeType ->
for the lambda, where SomeType
is Float
in this case. (because Leaf :: Float -> Tree
, so if Leaf
is applied to a
, then a :: Float
) This gives us Float -> ???
Now we find the type of the lambda-less expression Leaf (a :: Float)
, which is Tree
because Leaf :: Float -> Tree
. Now we can add substitute Tree
for ???
to get Float -> Tree
, the actual type of func
.
As you can see, we did that all by just looking at the source code. This means that no matter what, func
will always have that type, so there is no need to check whether or not it does. In fact, the compiler will throw out all information about the type of func
when it compiles your code, and your code will still work properly because of type-checking. (The caveat to this (Typeable
) is pointed out in the other answer)
TL;DR: Haskell is statically typed, so func
always has the type Float -> Tree
, so asking how to check whether that is true doesn't make sense.
Upvotes: 0
Reputation: 60513
Well, there are a few answers, which zigzag in their answers to "is this possible".
You could ask ghci
ghci> :t func
func :: Float -> Tree
which tells you the type.
But you said in your comment that you are wanting to write
if func == Tree then 0 else 1
which is not possible. In particular, you can't write any function like
isTree :: a -> Bool
isTree x = if x :: Tree then True else False
because it would violate parametericity, which is a neat property that all polymorphic functions in Haskell have, which is explored in the paper Theorems for Free.
But you can write such a function with some simple generic mechanisms that have popped up; essentially, if you want to know the type of something at runtime, it needs to have a Typeable
constraint (from the module Data.Typeable
). Almost every type is Typeable
-- we just use the constraint to indicate the violation of parametericity and to indicate to the compiler that it needs to pass runtime type information.
import Data.Typeable
import Data.Maybe (isJust)
data Tree = Leaf Float | ...
deriving (Typeable) -- we need Trees to be typeable for this to work
isTree :: (Typeable a) => a -> Bool
isTree x = isJust (cast x :: Maybe Tree)
But from my experience, you probably don't actually need to ask this question. In Haskell this question is a lot less necessary than in other languages. But I can't be sure unless I know what you are trying to accomplish by asking.
Upvotes: 3