Как определить функцию в ghci через несколько строк?

Я пытаюсь определить любую простую функцию, которая охватывает несколько строк в 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, что мне не хватает?

Ответ 1

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

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) }

Ответ 2

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

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

Ответ 3

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

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

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

> :{
| 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 ()

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

Ответ 5

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

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

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

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

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