I would like to define a data type in Haskell which is parametrized by an Int
constant along the lines:
data Q (n :: Int) = Q n (Int,Int) -- non-working code
in order to allow me to define functions of the type:
addQ :: (Q n)->(Q n)->(Q n)
addQ (Q k (i1,j1)) (Q k (i2,j2))) = Q k (i1+i2,j1+j2)
The idea is that in this way I am able to restrict addition to Q
's that have the same n
. Intuitively, it feels that this should be possible, but so far all my (admittedly newbie) attempts have stranded on the rigors of GHC.
The Data Keyword and Constructors In general, we define a new data type by using the data keyword, followed by the name of the type we're defining. The type has to begin with a capital letter to distinguish it from normal expression names. To start defining our type, we must provide a constructor.
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. To learn more about the Type, we will use the ":t" command.
The result of show is a syntactically correct Haskell expression containing only constants, given the fixity declarations in force at the point where the type is declared. It contains only the constructor names defined in the data type, parentheses, and spaces.
As the comments say, this is possible with the DataKinds extension (technically it's possible to achieve something very similar without it, but it's very unergonomic).
{-# LANGUAGE DataKinds, ExplicitForAll, KindSignatures #-}
import GHC.TypeLits (Nat)
data Q (n :: Nat) = Q Int
addQ :: forall (n :: Nat). Q n -> Q n -> Q n
addQ (Q x) (Q y) = Q (x + y)
let q1 = Q 1 :: Q 3
q2 = Q 2 :: Q 3
in addQ q1 q2
-- => Q 3 :: Q 3
If you put the KnownNat
constraint on n
(also from GHC.TypeLits
) you can also get the n
as a regular term using the natVal
function.
Based on the hints and answer kindly supplied, I can give the answer I was looking for, including an example of how to unpack n
from the parametrized data type.
{-# LANGUAGE DataKinds, ExplicitForAll, KindSignatures #-}
import GHC.TypeLits (Nat,KnownNat,natVal)
data Q (n :: Nat) = Q (Int,Int)
instance (KnownNat n) => Show (Q n) where
show q@(Q (i,j)) = "("++(show i)++","++(show j)++")::"++(show (natVal q))
addQ :: forall (n :: Nat). Q n -> Q n -> Q n
addQ (Q (i1,j1)) (Q (i2,j2)) = Q (i1+i2,j1+j2)
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