Многострочные команды в GHCi - PullRequest
       6

Многострочные команды в GHCi

115 голосов
/ 09 декабря 2011

У меня проблема с вводом многострочных команд в ghci.

Следующий двухстрочный код работает из файла:

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

Но когда я вхожу в ghci, я получаю ошибку:

<interactive>:1:1: error:
    Variable not in scope: addTwo :: Int -> Int -> Int

Я также пытался поместить код внутри :{ ... :}, но они также не работают для этого примера, потому что это просто добавление строк в одну строку, что не должно быть.

Я использую WinGHCi, версия 2011.2.0.1

Ответы [ 4 ]

160 голосов
/ 09 декабря 2011

Большую часть времени вы можете рассчитывать на вывод типа для вашей подписи. В вашем примере достаточно следующего:

Prelude> let addTwo x y = x + y

Если вам действительно нужно определение с сигнатурой типа или ваше определение занимает несколько строк, вы можете сделать это в ghci:

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

Обратите внимание, что вы также можете сжать это в одну строку:

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

Подробнее о взаимодействии с ghci вы можете узнать в Интерактивная оценка в разделе документации.

103 голосов
/ 12 ноября 2012

Решите эту проблему, запустив GHCI и набрав :set +m:

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

Boom.


Что здесь происходит (и я в основном говорю you , человек, который ищет помощь во время прохождения Learn You A Haskell ), - это то, что GHCI - это интерактивная среда, в которой вы меняете привязки имен функций на лету.Вы должны обернуть свои определения функций в блок let, чтобы Haskell знал, что вы собираетесь что-то определить.Материал :set +m является сокращением для многострочного :{ кода :} конструкции.

Пробелы также имеют большое значение в блоках, поэтому вы должны отступать от определения функции после определения типа.на четыре пробела, чтобы учесть четыре пробела в let.

13 голосов
/ 09 декабря 2011

Использование let:

Prelude> :{
Prelude| let addTwo :: Int -> Int -> Int
Prelude|     addTwo x y = x + y
Prelude| :}
Prelude> addTwo 2 3
5
3 голосов
/ 30 декабря 2018

Начиная с GHCI версии 8.0.1 , let больше не требуется для определения функций в REPL.

Так что это должно работать для вас:

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

Вывод типа в Haskell обеспечивает обобщенную типизацию, которая работает и для чисел с плавающей запятой:

λ: addTwo 2.0 1.0
3.0

Если вы должны предоставить свою собственную типизацию, вам, вероятно, придется использовать let в сочетании с многострочным вводом(используйте :set +m для включения многострочного ввода в GHCI):

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

Но вы получите ошибки, если попытаетесь передать что-либо кроме Int из-за вашей неполиморфной типизации:

λ: 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
...