This is a minimal example taken from the Reflection-0.5.
{-# LANGUAGE Rank2Types, MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-}
{-# OPTIONS_GHC -fno-cse -fno-full-laziness -fno-float-in #-}
import Control.Applicative
import Data.Proxy
newtype Zero = Zero Zero deriving (Show)
class ReifiesNum s where
reflectNum :: Num a => proxy s -> a
instance ReifiesNum Zero where
reflectNum = pure 0
In GHCi, I get the following:
>:t Zero
Zero :: Zero -> Zero
This makes sense: I'm asking for the type of the constructor which takes a Zero and returns a Zero.
>:t reflectNum
reflectNum :: (ReifiesNum s, Num a) => proxy s -> a
It makes sense that I could write something like
>let x = Just (undefined::Zero)
>reflectNum x
because the type Just Zero matches the type variables 'proxy s'.
Finally, the confusing part:
>:t (reflectNum Zero)
(reflectNum Zero) :: Num a => a
I do not understand how the type of the constructor Zero :: Zero -> Zero apparently matches the type variables 'proxy s', but apparently it does because the type of (reflectNum Zero) is just 'a'.
I'd appreciate help understanding this example, and links to relevant concepts would be greatly appreciated.
Thanks
If you are using an interactive Haskell prompt (like GHCi) you can type :t <expression> and that will give you the type of an expression. e.g. or e.g.
The == is an operator for comparing if two things are equal. It is quite normal haskell function with type "Eq a => a -> a -> Bool". The type tells that it works on every type of a value that implements Eq typeclass, so it is kind of overloaded.
So no, Haskell types do not exist at runtime, in any form.
In Haskell, every statement is considered as a mathematical expression and the category of this expression is called as a Type. You can say that "Type" is the data type of the expression used at compile time.
It's just the infix syntax of the function arrow throwing you off. First, here's an example with an easy-to-understand case: Maybe Int
. To make it match proxy s
, we just set:
proxy = Maybe
s = Int
Now let's pretend a -> b
is instead written Fun a b
, and so Zero
has type Fun Zero Zero
(i.e. (Fun Zero) Zero
). To make it match proxy s
, we set:
proxy = Fun Zero
s = Zero
In reality, proxy
is (->) Zero
, and so proxy s
is ((->) Zero) Zero
≡ (->) Zero Zero
≡ Zero -> Zero
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With