Juan Pablo Yamamoto
jpyamamoto[at]ciencias.unam.mx
Lógica Computacional II. Semestre 2025-1.
{-# LANGUAGE GADTs #-}
Codificamos los tipos naturales al nivel de tipos, no nos interesa que tengamos términos que los representen (constructores).
data Zero
data Succ n
Teniendo números naturales, podemos codificar los vectores como listas dependientes de un natural.
xs de tamaño n, Cons x xs es un vector de tamaño n+1data Vec a n where
Void :: Vec a Zero
Cons :: a -> Vec a n -> Vec a (Succ n)
instance Show a => Show (Vec a n) where
show Void = "Void"
show (Cons x xs) = "(Cons " ++ show x ++ " " ++ show xs ++ ")"
:t Void
:t Cons 1 Void
:t Cons 1 (Cons 2 Void)
Definición de head:
headVec :: Vec a (Succ n) -> a
headVec (Cons x _) = x
:t headVec (Cons 1 Void)
:t headVec Void
<interactive>:1:9: error:
• Couldn't match type ‘Zero’ with ‘Succ n0’
Expected: Vec a (Succ n0)
Actual: Vec a Zero
• In the first argument of ‘headVec’, namely ‘Void’
In the expression: headVec Void
:t head []
head []
Prelude.head: empty list CallStack (from HasCallStack): error, called at libraries/base/GHC/List.hs:1646:3 in base:GHC.List errorEmptyList, called at libraries/base/GHC/List.hs:85:11 in base:GHC.List badHead, called at libraries/base/GHC/List.hs:81:28 in base:GHC.List head, called at <interactive>:1:1 in interactive:Ghci169
Definición de tail:
tailVec :: Vec a (Succ n) -> Vec a n
tailVec (Cons _ xs) = xs
:t tailVec (Cons 1 Void)
:t tailVec Void
<interactive>:1:9: error:
• Couldn't match type ‘Zero’ with ‘Succ n’
Expected: Vec a (Succ n)
Actual: Vec a Zero
• In the first argument of ‘tailVec’, namely ‘Void’
In the expression: tailVec Void
:t tail []
tail []
Prelude.tail: empty list CallStack (from HasCallStack): error, called at libraries/base/GHC/List.hs:1646:3 in base:GHC.List errorEmptyList, called at libraries/base/GHC/List.hs:128:28 in base:GHC.List tail, called at <interactive>:1:1 in interactive:Ghci237
Definición de map:
mapVec :: (a -> b) -> Vec a n -> Vec b n
mapVec f Void = Void
mapVec f (Cons x xs) = Cons (f x) (mapVec f xs)
¿Cuál sería el tipo que corresponde?
append :: Vec a m -> Vec a n -> Vec a ???
data Sum m n s where
SumZero :: Sum Zero n n
SumSucc :: Sum m n s -> Sum (Succ m) n (Succ s)
instance Show (Sum m n s) where
show SumZero = "SumZero"
show (SumSucc n) = "(SumSucc " ++ show n ++ ")"
Damos evidencia de los tipos, para definir la suma.
append :: Sum m n s -> Vec a m -> Vec a n -> Vec a s
append SumZero Void ys = ys
append (SumSucc p) (Cons x xs) ys = Cons x (append p xs ys)
append SumZero Void (Cons 2 Void)
(Cons 2 Void)
:t SumSucc SumZero
append (SumSucc (SumSucc SumZero)) (Cons 1 (Cons 2 (Cons 3 Void))) (Cons 4 Void)
<interactive>:1:53: error:
• Couldn't match type ‘Succ Zero’ with ‘Zero’
Expected: Vec a Zero
Actual: Vec a (Succ Zero)
• In the second argument of ‘Cons’, namely ‘(Cons 3 Void)’
In the second argument of ‘Cons’, namely ‘(Cons 2 (Cons 3 Void))’
In the second argument of ‘append’, namely ‘(Cons 1 (Cons 2 (Cons 3 Void)))’
fromList :: [a] -> Vec a n
fromList [] = Void
fromList (x:xs) = Cons x (fromList xs)
<interactive>:2:15: error:
• Couldn't match type ‘n’ with ‘Zero’
Expected: Vec a n
Actual: Vec a Zero
‘n’ is a rigid type variable bound by
the type signature for:
fromList :: forall a n. [a] -> Vec a n
at <interactive>:1:1-26
• In the expression: Void
In an equation for ‘fromList’: fromList [] = Void
• Relevant bindings include fromList :: [a] -> Vec a n (bound at <interactive>:2:1)