Как определить функцию в ghci через несколько строк? - PullRequest
142 голосов
/ 17 мая 2010

Я пытаюсь определить любую простую функцию, которая занимает несколько строк в ghci, возьмем в качестве примера следующее:

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

Пока я пытался нажать Enter после первой строки:

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

Я также пытался использовать команды :{ и :}, но далеко не уйду:

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

Я использую GHC Interactive версии 6.6 для Haskell 98 в Linux, чего мне не хватает?

Ответы [ 5 ]

233 голосов
/ 06 ноября 2013

GHCi теперь имеет режим многострочного ввода, который активируется с помощью: set + m. Например,

Prelude> :set +m
Prelude> let fac 0 = 1
Prelude|     fac n = n * fac (n-1)
Prelude|
Prelude> fac 10
3628800
116 голосов
/ 17 мая 2010

для охранников (как в вашем примере), вы можете просто поместить их всех в одну строку, и это работает (охранники не заботятся о расстоянии)

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

если вы хотите написать свою функцию с несколькими определениями, которые соответствуют шаблону аргументов, например:

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

тогда вы будете использовать фигурные скобки с точкой с запятой, разделяющие определения

let { fact 0 = 1 ; fact n = n * fact (n-1) }
52 голосов
/ 20 августа 2010

Дан правильный, но :{ и :} должны отображаться в отдельной строке:

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

Это также взаимодействует с правилом макета, поэтому при использовании нотации может быть проще использовать явные скобки и точки с запятой. Например, это определение не выполняется:

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

Но это работает, когда добавляются скобки и точки с запятой:

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

Это будет действительно иметь значение только при вставке определений из файла, где может измениться отступ.

17 голосов
/ 17 мая 2010

Похоже, :{ и :} - довольно новая функция. Возможно, вам потребуется обновить GHC.

Редактировать: подтверждено, см. http://www.haskell.org/ghc/docs/6.8.2/html/users_guide/release-6-8-2.html

7 голосов
/ 17 мая 2010

Если вы не хотите обновлять GHC только для :{ и :}, вам нужно написать все это в одну строку:

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

Я не знаю ни одного определения в Haskell, которое должно быть написано в несколько строк. Вышесказанное действительно работает в GHCi:

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

Для других выражений, таких как do блоки, вам нужно использовать синтаксис без макета с фигурными скобками и точками с запятой (eugh).

...