web-dev-qa-db-fra.com

Commandes multilignes dans GHCi

J'ai des problèmes pour entrer des commandes multi-lignes dans ghci.

Le code à 2 lignes suivant fonctionne à partir d'un fichier:

addTwo :: Int -> Int -> Int
addTwo x y = x + y

Mais quand j'entre en ghci, j'obtiens des erreurs. 

J'ai aussi essayé de mettre le code dans :{ ... :}, mais ils ne fonctionnent pas non plus pour cet exemple, car il s'agit simplement d'ajouter les lignes sur une ligne, ce qui ne devrait pas être le cas.

J'utilise WinGHCi, version 2011.2.0.1

108
R71

La plupart du temps, vous pouvez compter sur l'inférence de type pour élaborer une signature à votre place. Dans votre exemple, ce qui suit suffit:

Prelude> let addTwo x y = x + y

Si vous voulez vraiment une définition avec une signature de type, ou si votre définition s'étend sur plusieurs lignes, vous pouvez le faire en ghci:

Prelude> :{
Prelude| let addTwo :: Int -> Int -> Int
Prelude|     addTwo x y = x + y 
Prelude| :}
Prelude> addTwo 4 7
11

Notez que vous pouvez également compresser ceci sur une ligne:

Prelude> let addTwo :: Int -> Int -> Int ; addTwo x y = x + y

Pour en savoir plus sur l’interaction avec ghci, consultez l’évaluation Interactive à la section Prompt de la documentation.

151
Nicolas Wu

Résolvez ce problème en activant GHCI et en tapant :set +m:

Prelude> :set +m
Prelude> let addTwo :: Int -> Int -> Int
Prelude|     addTwo x y = x + y
Prelude| 
Prelude> addTwo 1 3
4

Boom.


Que se passe-t-il ici (et je parle principalement de vous, personne cherchant de l’aide pendant que vous avancez dans Learn You A Haskell ) est que GHCI est un environnement interactif dans lequel vous modifiez les liens de noms de fonction à la volée. Vous devez envelopper vos définitions de fonctions dans un bloc let, afin que Haskell sache que vous êtes sur le point de définir quelque chose. Le code :set +m est un raccourci pour la construction multiligne :{code:}.

Les espaces sont également significatifs dans les blocs, vous devez donc indenter votre définition de fonction après votre définition de type de quatre espaces pour prendre en compte les quatre espaces dans let.

94
adrian

Utilisez let:

Prelude> :{
Prelude| let addTwo :: Int -> Int -> Int
Prelude|     addTwo x y = x + y
Prelude| :}
Prelude> addTwo 2 3
5
13
Stefan Holdermans

A partir de GHCI version 8.0.1 , let n'est plus nécessaire pour définir des fonctions sur le REPL.

Donc, cela devrait bien fonctionner pour vous:

λ: addTwo x y = x + y
λ: addTwo 1 2
3
λ: :t addTwo
addTwo :: Num a => a -> a -> a

L'inférence de type de Haskell fournit un typage généralisé qui fonctionne également pour les flottants:

λ: addTwo 2.0 1.0
3.0

Si vous devez fournir votre propre frappe, il semble que vous deviez utiliser let combiné avec une entrée multiligne (utilisez :set +m pour activer la saisie multiligne dans GHCI):

λ: let addTwo :: Int -> Int -> Int
 |     addTwo x y = x + y
 | 
λ: addTwo 1 2
3

Mais vous obtiendrez des erreurs si vous essayez de transmettre autre chose qu'une Int à cause de votre typage non polymorphe:

λ: addTwo 2.0 1.0

<interactive>:34:8: error:
    • No instance for (Fractional Int) arising from the literal ‘2.0’
    • In the first argument of ‘addTwo’, namely ‘2.0’
      In the expression: addTwo 2.0 1.0
      In an equation for ‘it’: it = addTwo 2.0 1.0
0
Aaron Hall