Un hecho poco conocido es que si activa suficientes extensiones de idioma (ghc), ¡Haskell se convierte en un lenguaje interpretado de tipo dinámico! Por ejemplo, el siguiente programa implementa la suma.
{-# Language MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-}
data Zero
data Succ a
class Add a b c | a b -> c
instance Add Zero a a
instance (Add a b c) => Add (Succ a) b (Succ c)
Esto ya no se parece a Haskell. Para uno en lugar de operar sobre objetos, operamos sobre tipos. Cada número es su propio tipo. En lugar de funciones tenemos clases de tipo. Las dependencias funcionales nos permiten usarlas como funciones entre tipos.
Entonces, ¿cómo invocamos nuestro código? Usamos otra clase
class Test a | -> a
where test :: a
instance (Add (Succ (Succ (Succ (Succ Zero)))) (Succ (Succ (Succ Zero))) a)
=> Test a
Esto establece el tipo de test
al tipo 4 + 3. Si abrimos esto en ghci, encontraremos que de test
hecho es del tipo 7:
Ok, one module loaded.
*Main> :t test
test :: Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero))))))
Tarea
Quiero que implementes una clase que multiplique dos números Peano (enteros no negativos). Los números de Peano se construirán utilizando los mismos tipos de datos en el ejemplo anterior:
data Zero
data Succ a
Y su clase será evaluada de la misma manera que arriba también. Puedes nombrar tu clase como quieras.
Puede usar cualquier extensión de idioma ghc que desee sin costo para los bytes.
Casos de prueba
Estos casos de prueba asumen que su clase se llama M
, puede nombrarla de otra manera si lo desea.
class Test1 a| ->a where test1::a
instance (M (Succ (Succ (Succ (Succ Zero)))) (Succ (Succ (Succ Zero))) a)=>Test1 a
class Test2 a| ->a where test2::a
instance (M Zero (Succ (Succ Zero)) a)=>Test2 a
class Test3 a| ->a where test3::a
instance (M (Succ (Succ (Succ (Succ Zero)))) (Succ Zero) a)=>Test3 a
class Test4 a| ->a where test4::a
instance (M (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))) (Succ (Succ (Succ Zero))) a)=>Test4 a
Resultados
*Main> :t test1
test1
:: Succ
(Succ
(Succ
(Succ
(Succ (Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))))))))
*Main> :t test2
test2 :: Zero
*Main> :t test3
test3 :: Succ (Succ (Succ (Succ Zero)))
*Main> :t test4
test4
:: Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))))))))))))))
Se inspira en escribir la entrevista técnica