web-dev-qa-db-fra.com

Comment définir une fonction en ghci sur plusieurs lignes?

J'essaie de définir n'importe quelle fonction simple qui s'étend sur plusieurs lignes dans ghci, prenons l'exemple suivant:

let abs n | n >= 0 = n
          | otherwise = -n

Jusqu'à présent, j'ai essayé d'appuyer sur Entrée après la première ligne:

Prelude> let abs n | n >= 0 = n
Prelude>           | otherwise = -n
<interactive>:1:0: parse error on input `|'

J'ai aussi essayé d'utiliser le :{ et :} commandes mais je ne vais pas loin:

Prelude> :{
unknown command ':{'
use :? for help.

J'utilise GHC Interactive version 6.6 pour Haskell 98 sous Linux, que me manque-t-il?

143
Peter McG

pour les gardes (comme votre exemple), vous pouvez simplement les mettre tous sur une seule ligne et cela fonctionne (les gardes ne se soucient pas de l'espacement)

let abs n | n >= 0 = n | otherwise = -n

si vous voulez écrire votre fonction avec plusieurs définitions, ce modèle correspond aux arguments, comme ceci:

fact 0 = 1
fact n = n * fact (n-1)

alors vous utiliseriez des accolades avec des points-virgules séparant les définitions

let { fact 0 = 1 ; fact n = n * fact (n-1) }
117
newacct

GHCi a maintenant un mode de saisie multiligne, activé avec: set + m. Par exemple,

Prelude> :set +m
Prelude> let fac 0 = 1
Prelude|     fac n = n * fac (n-1)
Prelude|
Prelude> fac 10
3628800
235
karakfa

Dan a raison, mais :{ et :} doivent apparaître sur leur propre ligne:

> :{ 
> let foo a b = a +
>           b
> :}
> :t foo
foo :: (Num a) => a -> a -> a

Cela interagit également avec la règle de présentation. Ainsi, lorsque vous utilisez la notation Do, il peut être plus facile d’utiliser explicitement les accolades et les points-virgules. Par exemple, cette définition échoue:

> :{
| let prRev = do
|   inp <- getLine
|   putStrLn $ reverse inp
| :}
<interactive>:1:18:
    The last statement in a 'do' construct must be an expression

Mais cela fonctionne lorsque des accolades et des points-virgules sont ajoutés:

> :{
| let prRev = do {
|   inp <- getLine;
|   putStrLn $ reverse inp;
| }
| :}
> :t prRev
prRev :: IO ()

Cela importera vraiment uniquement lors du collage de définitions à partir d'un fichier, où l'indentation peut changer.

53
Justin Bailey

Ça ressemble à :{ et :} sont une jolie nouveauté. Vous devrez peut-être mettre à niveau GHC.

Edit: confirmé, voir http://www.haskell.org/ghc/docs/6.8.2/html/users_guide/release-6-8-2.html

17
Dan

Si vous ne voulez pas mettre à jour GHC juste pour :{ et :}, vous aurez besoin de tout écrire sur une seule ligne:

> let abs' n | n >= 0 = n | otherwise = -n

Je ne connais pas de définition unique dans Haskell qui doit soit écrite sur plusieurs lignes. Ce qui précède fonctionne bien dans GHCi:

> :t abs'
abs' :: (Num a, Ord a) => a -> a

Pour les autres expressions, telles que les blocs do, vous devrez utiliser la syntaxe non-layout avec des accolades et des points-virgules (eugh).

7
C. A. McCann