You can't use integer literals in a new type like that. They are already taken, so it isn't valid syntax.
cdk's answer gives a much more practical scenario, but I thought I would give an example of how something like your last example could be implemented in Haskell.
If we turn on some of the more fun extensions, we can convince GHC to make a type with a given finite number of values. I probably wouldn't suggest actually doing this in real code, however, because GHC doesn't have the best support for this kind of dependent type-like programming at the moment. Also, unfortunately, the values don't have nice names. As far as I know, there isn't a way to give them nice names like 1, 2, 3...
(edit: actually, we can improve on this a little bit, see the second code block).
It could go something like this:
{-# LANGUAGE GADTs, DataKinds, KindSignatures, TypeOperators #-}
module Fin (Fin (..))
where
import GHC.TypeLits
data Fin :: Nat -> * where
FZero :: Fin upperBound
FSucc :: (1 <= upperBound) => Fin upperBound -> Fin (upperBound + 1)
fifthValue :: Fin 5
fifthValue = FSucc (FSucc (FSucc FZero))
Note that to actually get instances for things like Eq
and Ord
you might have to do even more tricky things (I'm not even totally sure if it's possible. It might need the new type level natural number theorem prover that they're putting in GHC 7.10).
One other thing I should probably point out is that the types that inhabit the kind Nat
are named 1, 2, ...
. This is ok because there isn't anything else that use those names at a type level (just at a value level).
Edit:
If we turn on a couple more extensions, we can get a version where you can (almost) directly specify the names of the values:
{-# LANGUAGE DataKinds, KindSignatures, GADTs, TypeOperators, PolyKinds, TypeFamilies, UndecidableInstances
import Data.Type.Equality
import GHC.TypeLits
type family (||) (a :: Bool) (b :: Bool) :: Bool where
True || x = True
False || x = x
type family Elem (a :: k) (xs :: [k]) :: Bool where
Elem x (y ': ys) = (x == y) || Elem x ys
Elem x '[] = False
data NamedFin :: [k] -> * where
Val :: ((a `Elem` as) ~ True) => Proxy a -> NamedFin as
-- Countdown n makes a type level list of Nats.
-- So, for example, Countdown 3 is a shorthand for '[3, 2, 1]
type family Countdown (a :: Nat) :: [Nat] where
Countdown 0 = '[]
Countdown n = (n - 1) ': Countdown (n - 1)
data Proxy a = Proxy deriving Show
type Example = NamedFin (Countdown 5) -- This is the same as NamedFin '[5, 4, 3, 2, 1]
-- This compiles...
example :: Example
example = Val (Proxy :: Proxy 4)
-- ...but this doesn't
-- example2 :: Example
-- example2 = Val (Proxy :: Proxy 10)
There will still be issues making instances for Eq
and Ord
though.
Int
takes place in a theoretical world where theInt
type has not been defined and therefore the "symbols" of the numbers don't have meaning yet. It doesn't work in reality because, in reality, theInt
type does exist and those numbers have a meaning, so they can't be used as value constructors. – ApproachingDarknessFishFin
, for "finite". – David Young