Pdepreludat es una biblioteca que busca hacer más amigable y didáctico al Prelude de haskell, por ejemplo mejorando ciertos mensajes de error.
Si estás usando Linux, podés correr el siguiente comando:
curl -sSL https://get.haskellstack.org/ | sh
Si estás usando Windows, podés descargarlo haciendo click acá.
Para más información podés ir a la página oficial de stack.
Correr el siguiente comando que va a crear una carpeta llamada proyecto-test
(o el nombre que le hayan pasado stack new
) con el proyecto adentro:
stack new proyecto-test https://github.com/10Pines/pdepreludat/releases/latest/download/pdepreludat.hsfiles
Una vez creada la carpeta, moverse a la misma y compilar el proyecto con los siguientes comandos:
cd proyecto-test
stack build --test
Ahora ya debería haber descargado e instalado todo lo necesario para funcionar, para poder correr el intérprete, ejecutar:
stack ghci
También, se pueden correr los tests usando:
stack test
La biblioteca exporta un módulo que contiene la mayoría de las funciones existentes en el Prelude, con ciertas modificaciones:
- Fue redefinido el tipo de las funciones que trabajan sobre
Foldable t
para que trabajen sobre[]
> :t any
any :: Foldable t => (a -> Bool) -> t a -> Bool
> :t any
any :: (a -> Bool) -> [a] -> Bool
A efectos prácticos, el tipo Number es lo mismo que un Double, y todas las funciones que usaban cualquier otro tipo de número o algún tipo numérico más general fueron redefinidas para que trabajen con Number. Este es el cambio más disruptivo o que rompe más la compatibilidad con el resto del mundo de Haskell.
La idea es que ayude en:
> :t 5
5 :: Num p => p
> :t 5
5 :: Number
> sum + 5
<interactive>:9:1: error:
Non type-variable argument in the constraint: Num (t a -> a)
(Use FlexibleContexts to permit this)
When checking the inferred type
//...más errores
> sum + 5
<interactive>:9:1: error:
• Couldn't match expected type ‘Number’
with actual type ‘[Number] -> Number’
• Probable cause: ‘sum’ is applied to too few arguments
//...más errores
> sum [1,2,3,4] / length [1,2,3,4]
<interactive>:7:1: error:
• No instance for (Fractional Int) arising from a use of ‘/’
• In the expression: sum [1, 2, 3, 4] / length [1, 2, 3, 4]
In an equation for ‘it’:
it = sum [1, 2, 3, ....] / length [1, 2, 3, ....]
> sum [1,2,3,4] / length [1,2,3,4]
2.5
El trade off más grande que hubo que hacer para permitir esas cosas, es que muchos errores en tiempo de compilación se movieron a tiempo de ejecución, es decir, los números ahora son menos type safe.
Esto ni siquiera tipa:
> :t take 2.5 [1,2,3,4]
<interactive>:1:6: error:
• Could not deduce (Fractional Int) arising from the literal ‘2.5’
from the context: Num a
bound by the inferred type of it :: Num a => [a]
at <interactive>:1:1
Esto tipa
> :t take 2.5 [1,2,3,4]
take 2.5 [1,2,3,4] :: [Number]
Pero falla en ejecución
> take 2.5 [1,2,3,4]
*** Exception: Se esperaba un valor entero pero se pasó uno con decimales
CallStack (from HasCallStack):
error, called at /home/juan/Development/Proyectos/10pines/pdepreludat/src/Number.hs:11:39 in main:Number
Se definió una instancia de Show
para las funciones
> filter
<interactive>:2:1: error:
No instance for (Show ((a0 -> Bool) -> [a0] -> [a0]))
arising from a use of ‘print’
// ...más errores
> filter
<una función>
Se agregó la función toFloat
para convertir enteros a decimales, ya que creemos que fromIntegral
puede ser un poco confuso de usar, y se agregaron mejores mensajes de error a las operaciones donde se esperaba un decimal y llegó un entero o viceversa.
> sum [1,2] / length [1,2]
<interactive>:3:1: error:
No instance for (Fractional Int) arising from a use of ‘/’
In the expression: sum [1, 2] / length [1, 2]
// ...más errores
> sum [1,2] / length [1,2]
<interactive>:1:1: error:
• Estás operando enteros con fraccionales, que son diferentes tipos. Podés convertir el entero en decimal usando toFloat/1 o el decimal en entero usando round/1, floor/1 o ceiling/1.
• In the expression: sum [1, 2] / length [1, 2]
In an equation for ‘it’: it = sum [1, 2] / length [1, 2]
> filter == map
<interactive>:1:1: error:
• No instance for (Eq ((Bool -> Bool) -> [Bool] -> [Bool]))
arising from a use of ‘==’
(maybe you haven't applied a function to enough arguments?)
• In the expression: filter == map
In an equation for ‘it’: it = filter == map
> filter == map
<interactive>:1:1: error:
• Las funciones no se pueden ordenar ni comparar.
• In the expression: filter == map
In an equation for ‘it’: it = filter == map
Podés ver la wiki