Skip to content

Instantly share code, notes, and snippets.

@HirotoShioi
Last active November 7, 2019 00:31
Show Gist options
  • Save HirotoShioi/cc4172507f2fe183f19beb31b62f5681 to your computer and use it in GitHub Desktop.
Save HirotoShioi/cc4172507f2fe183f19beb31b62f5681 to your computer and use it in GitHub Desktop.
Haskellにおける型レベルプログラミングの基本(翻訳) ref: https://qiita.com/HirotoShioi/items/39fc492401e4dcbc8cba
data Unit = MkUnit
data Bool = True | False
data IntAndChar = MkIntAndChar Int Char
data HigherKinded f a
= Bare a
| Wrapped (f a)
λ> :kind HigherKinded
HigherKinded :: (* -> *) -> * -> *
λ> data Void
λ> :kind Void
Void :: *
data Zero
data Succ a
type One = Succ Zero
type Two = Succ One
type Three = Succ Two
type Four = Succ (Succ (Succ (Succ Zero)))
{-# LANGUAGE DataKinds #-}
data Nat = Zero | Succ Nat
λ> :kind 'Zero
'Zero :: Nat
λ> :kind 'Succ
'Succ :: Nat -> Nat
λ> :type Zero
Zero :: Nat
λ> :type Succ
Succ :: Nat -> Nat
{-# LANGUAGE GADTs #-}
data Maybe a where
Just :: a -> Maybe a
Nothing :: Maybe a
theFirstOne = MkIntAndChar 3 'a'
theSecond = MkIntAndChar (-3) 'b'
data IntBool a where
Int :: Int -> IntBool Int
Bool :: Bool -> IntBool Bool
extractIntBool :: IntBool a -> a
extractIntBool (Int _) = 0
extractIntBool (Bool b) = b
data Vector (n :: Nat) a where
{-# LANGUAGE KindSignatures #-}
VNil :: Vector 'Zero a
VCons :: a -> Vector n a -> Vector ('Succ n) a
data Vector (n :: Nat) (a :: *) where
VNil :: Vector 'Zero a
VCons :: a -> Vector n a -> Vector ('Succ n) a
data Vector n a where
VNil :: Vector Zero a
VCons :: a -> Vector n a -> Vector (Succ n) a
instance Show a => Show (Vector n a) where
show VNil = "VNil"
show (VCons a as) = "VCons " ++ show a ++ " (" ++ show as ++ ")"
{-# LANGUAGE TypeFamilies #-}
λ> :t MkIntAndChar
MkIntAndChar :: Int -> Char -> IntAndChar
add :: Nat -> Nat -> Nat
add Zero n = n
add (Succ n) m = add n (Succ m)
add :: Nat -> Nat -> Nat
add Zero n = n
add (Succ n) m = add n (Succ m)
type family Add n m where
Add 'Zero n = n
Add ('Succ n) m = Add n ('Succ m)
• The type family application ‘Add n ('Succ m)’
is no smaller than the instance head
(Use UndecidableInstances to permit this)
• In the equations for closed type family ‘Add’
In the type family declaration for ‘Add’
{-# LANGUAGE UndecidableInstances #-}
λ> :kind Add (Succ (Succ Zero)) (Succ Zero)
Add (Succ (Succ Zero)) (Succ Zero) :: Nat
λ> :kind! Add (Succ (Succ Zero)) (Succ Zero)
Add (Succ (Succ Zero)) (Succ Zero) :: Nat
= 'Succ ('Succ ('Succ 'Zero))
data Maybe a
= Just a
| Nothing
append :: Vector n a -> Vector m a -> Vector (Add n m) a
append VNil rest = VNil
• Could not deduce: m ~ 'Zero
from the context: n ~ 'Zero
bound by a pattern with constructor:
VNil :: forall a. Vector 'Zero a,
in an equation for ‘append’
at /home/matt/Projects/dep-types.hs:31:8-11
‘m’ is a rigid type variable bound by
the type signature for:
append :: forall (n :: Nat) a (m :: Nat).
Vector n a -> Vector m a -> Vector (Add n m) a
at /home/matt/Projects/dep-types.hs:30:11
Expected type: Vector (Add n m) a
Actual type: Vector 'Zero a
• In the expression: VNil
In an equation for ‘append’: append VNil rest = VNil
• Relevant bindings include
rest :: Vector m a
(bound at /home/matt/Projects/dep-types.hs:31:13)
append :: Vector n a -> Vector m a -> Vector (Add n m) a
(bound at /home/matt/Projects/dep-types.hs:31:1)
λ> :t append VNil
append VNil :: Vector m a -> Vector m a
append VNil xs = xs
append (VCons a rest) xs = append rest (VCons a xs)
λ> append (VCons 1 (VCons 3 VNil)) (VCons 2 VNil)
VCons 3 (VCons 1 (VCons 2 (VNil)))
append (VCons a rest) xs = VCons a (append rest xs)
λ> :reload
[1 of 1] Compiling DepTypes ( /home/matt/Projects/dep-types.hs, interpreted )
/home/matt/Projects/dep-types.hs:32:28: error:
• Could not deduce: Add n1 ('Succ m) ~ 'Succ (Add n1 m)
from the context: n ~ 'Succ n1
bound by a pattern with constructor:
VCons :: forall a (n :: Nat).
a -> Vector n a -> Vector ('Succ n) a,
in an equation for ‘append’
at /home/matt/Projects/dep-types.hs:32:9-20
Expected type: Vector (Add n m) a
Actual type: Vector ('Succ (Add n1 m)) a
• In the expression: VCons a (append rest xs)
In an equation for ‘append’:
append (VCons a rest) xs = VCons a (append rest xs)
• Relevant bindings include
xs :: Vector m a (bound at /home/matt/Projects/dep-types.hs:32:23)
rest :: Vector n1 a
(bound at /home/matt/Projects/dep-types.hs:32:17)
append :: Vector n a -> Vector m a -> Vector (Add n m) a
(bound at /home/matt/Projects/dep-types.hs:31:1)
Failed, modules loaded: none.
data Vector n a where
VNil :: Vector Zero a
VCons :: a -> Vector n a -> Vector (Succ n) a
type family Add x y where
Add 'Zero n = n
Add ('Succ n) m = Add n ('Succ m)
append :: Vector n a -> Vector m a -> Vector (Add n m) a
append VNil xs = xs
append (VCons a rest) xs = VCons a (append rest xs)
λ> :t Just
Just :: a -> Maybe a
λ> :t Nothing
Nothing :: Maybe a
append (VCons a rest) xs = VCons a (append rest xs)
type family Add x y where
Add 'Zero n = n
Add ('Succ n) m = 'Succ (Add n m)
{-# LANGUAGE TypeOperators #-}
data HList xs where
HNil :: HList '[]
(:::) :: a -> HList as -> HList (a ': as)
infixr 6 :::
λ> :t 'a' ::: 1 ::: "hello" ::: HNil
'a' ::: 1 ::: "hello" ::: HNil
:: HList '[Char, Int, String]
λ> 'a' ::: 1 ::: "hello" ::: HNil
\<interactive\>:13:1:
No instance for (Show (HList '[Char, Int, String]))
arising from a use of ‘print’
In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
instance Show (HList xs) where
show HNil = "HNil"
show (x ::: rest) = "_ ::: " ++ show rest
instance Show (HList '[]) where
show HNil = "HNil"
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
λ> let nothingA = Nothing :: Maybe a
λ> let nothingInt = Nothing :: Maybe Int
λ> let nothingChar = Nothing :: Maybe Char
λ> nothingInt == nothingChar
\<interactive\>:27:15: error:
• Couldn't match type ‘Char’ with ‘Int’
Expected type: Maybe Int
Actual type: Maybe Char
• In the second argument of ‘(==)’, namely ‘nothingChar’
In the expression: nothingInt == nothingChar
In an equation for ‘it’: it = nothingInt == nothingChar
λ> nothingA == nothingInt
True
λ> nothingA == nothingChar
True
instance (Show (HList as), Show a)
=> Show (HList (a ': as)) where
show (a ::: rest) =
show a ++ " ::: " ++ show rest
λ> 'a' ::: 1 ::: "hello" ::: HNil
'a' ::: 1 ::: "hello" ::: HNil
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeApplications #-}
newtype s >> a = Named a
data HRec xs where
HEmpty :: HRec '[]
HCons :: (s >> a) -> HRec xs -> HRec (s >> a ': xs)
λ> HCons (Named @"foo" 'a') (HCons (Named @"bar" (3 :: Int)) HEmpty)
\<interactive\>:10:1: error:
• No instance for (Show (HRec '["foo" >> Char, "bar" >> Int]))
arising from a use of ‘print’
• In a stmt of an interactive GHCi command: print it
λ> :t symbolVal
-- proxyを受け取って、その型をStringとして返す
symbolVal :: KnownSymbol n => proxy n -> String
λ> let a = (Proxy :: Proxy "hello")
λ> symbolVal a
"hello"
instance Show (HRec '[]) where
show _ = "HEmpty"
instance Show (HRec (s >> a ': xs)) where
instance Show (HRec (s >> a ': xs)) where
show (HCons (Named a) rest) =
instance (Show a)
=> Show (HRec (s >> a ': xs)) where
show (HCons (Named a) rest) =
let val = show a
λ> :type Maybe
\<interactive\>:1:1: error:
• Data constructor not in scope: Maybe
• Perhaps you meant variable ‘maybe’ (imported from Prelude
instance (Show a, KnownSymbol s)
=> Show (HRec (s >> a ': xs)) where
show (HCons (Named a) rest) =
let val = show a
key = symbolVal (Proxy :: Proxy s)
topLevelFunction :: a -> (a -> b) -> b
topLevelFunction a = go
where
go :: (a -> b) -> b
go f = f a
topLevelFunction :: a0 -> (a0 -> b0) -> b0
topLevelFunction a = go
where
go :: (a1 -> b1) -> b1
go f = f a
{-# LANGUAGE ScopedTypeVariables #-}
instance (Show a, KnownSymbol s, Show (HRec xs))
=> Show (HRec (s >> a ': xs)) where
show (HCons (Named a) rest) =
let val = show a
key = symbolVal (Proxy :: Proxy s)
more = show rest
in "(" ++ key ++ ": " ++ val ++ ") " ++ more
λ> HCons (Named @"foo" 'a') (HCons (Named @"bar" (3 :: Int)) HEmpty)
(foo: 'a') (bar: 3) HEmpty
λ> :kind Maybe
Maybe :: * -> *
λ> :kind Maybe
Maybe :: * -> *
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment