sobre - hola mundo en haskell
¿Cómo definir una función en ghci en múltiples líneas? (5)
Estoy tratando de definir cualquier función simple que abarque varias líneas en ghci, tome lo siguiente como ejemplo:
let abs n | n >= 0 = n
| otherwise = -n
Hasta ahora he intentado presionar Enter después de la primera línea:
Prelude> let abs n | n >= 0 = n
Prelude> | otherwise = -n
<interactive>:1:0: parse error on input `|''
También intenté usar los comandos :{
y :}
pero no llegué lejos:
Prelude> :{
unknown command '':{''
use :? for help.
Estoy usando GHC Interactive versión 6.6 para Haskell 98 en Linux, ¿qué me estoy perdiendo?
Dan está en lo correcto, pero :{
y :}
deben aparecer cada uno en su propia línea:
> :{
> let foo a b = a +
> b
> :}
> :t foo
foo :: (Num a) => a -> a -> a
Esto también interactúa con la regla de disposición, por lo que al usar la notación do es más fácil usar llaves y puntos y comas explícitamente. Por ejemplo, esta definición falla:
> :{
| let prRev = do
| inp <- getLine
| putStrLn $ reverse inp
| :}
<interactive>:1:18:
The last statement in a ''do'' construct must be an expression
Pero funciona cuando se agregan llaves y puntos y comas:
> :{
| let prRev = do {
| inp <- getLine;
| putStrLn $ reverse inp;
| }
| :}
> :t prRev
prRev :: IO ()
Esto solo importará cuando pegue definiciones de un archivo, donde la sangría podría cambiar.
GHCi ahora tiene un modo de entrada de línea múltiple, habilitado con: set + m. Por ejemplo,
Prelude> :set +m
Prelude> let fac 0 = 1
Prelude| fac n = n * fac (n-1)
Prelude|
Prelude> fac 10
3628800
Parece que :{
y :}
son una característica bastante nueva. Es posible que deba actualizar GHC.
Editar: confirmado, ver http://www.haskell.org/ghc/docs/6.8.2/html/users_guide/release-6-8-2.html
Si no quiere actualizar GHC solo por :{
y :}
, tendrá que escribirlo todo en una línea:
> let abs'' n | n >= 0 = n | otherwise = -n
No conozco ninguna definición única en Haskell que deba escribirse en múltiples líneas. Lo anterior, de hecho, funciona en GHCi:
> :t abs''
abs'' :: (Num a, Ord a) => a -> a
Para otras expresiones, como do
blocks, necesitará usar la sintaxis de no-disposición con llaves y puntos y comas (eugh).
para guardias (como su ejemplo), puede ponerlos todos en una línea y funciona (a los guardias no les importa el espaciado)
let abs n | n >= 0 = n | otherwise = -n
si quisiera escribir su función con múltiples definiciones que coincidan con los argumentos, como este:
fact 0 = 1
fact n = n * fact (n-1)
entonces usarías llaves con punto y coma separando las definiciones
let { fact 0 = 1 ; fact n = n * fact (n-1) }