Perintah multi-line di GHCi

134

Saya mengalami masalah dalam memasukkan perintah multi-line dalam ghci.

Kode 2-baris berikut ini berfungsi dari file:

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

Tetapi ketika saya masuk dalam ghci, saya mendapatkan kesalahan:

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

Saya juga mencoba memasukkan kode ke dalam :{ ... :}, tetapi mereka juga tidak bekerja untuk contoh ini, karena ini hanya menambahkan baris menjadi satu baris, yang seharusnya tidak terjadi.

Saya menggunakan WinGHCi, versi 2011.2.0.1

R71
sumber

Jawaban:

183

Sebagian besar waktu, Anda dapat mengandalkan inferensi tipe untuk mengerjakan tanda tangan untuk Anda. Dalam contoh Anda, berikut ini sudah cukup:

Prelude> let addTwo x y = x + y

Jika Anda benar-benar menginginkan definisi dengan tanda tangan jenis, atau definisi Anda mencakup beberapa baris, Anda dapat melakukannya dalam ghci:

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

Perhatikan bahwa Anda juga dapat menekan ini ke satu baris:

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

Anda dapat mengetahui lebih lanjut tentang berinteraksi dengan ghci pada evaluasi Interaktif di bagian prompt dokumentasi.

Nicolas Wu
sumber
1
Terima kasih banyak untuk kedua solusinya. Tapi saya punya pertanyaan terkait lainnya: mengapa empat blanko utama diperlukan di baris kedua (sebelum addTwo)? Dan ini harus tepat, jika ada lebih sedikit atau lebih banyak kekosongan, maka ada kesalahan.
R71
9
@Rog letmemulai blok; entri dalam blok dikelompokkan berdasarkan indentasi; dan karakter non-spasi putih pertama di blok menetapkan lekukan di mana mereka dikelompokkan. Karena karakter non-spasi pertama dalam letblok di atas adalah adari addTwo, semua baris dalam blok harus indentasi sedalam itu a.
Daniel Wagner
Terima kasih. Saya juga memperhatikan bahwa di blok membiarkan / di mana lainnya. Ini adalah perbedaan besar dari bahasa lain di mana spasi putih diabaikan, jadi saya mengalami kesulitan dalam memahami itu.
R71
124

Selesaikan masalah ini dengan menyalakan GHCI dan mengetik :set +m:

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

Ledakan.


Apa yang terjadi di sini (dan saya berbicara sebagian besar kepada Anda , orang mencari bantuan saat bekerja melalui Learn You A Haskell ) adalah bahwa GHCI adalah lingkungan interaktif tempat Anda mengubah ikatan nama fungsi dengan cepat. Anda harus membungkus definisi fungsi Anda dalam sebuah letblok, sehingga Haskell tahu bahwa Anda akan mendefinisikan sesuatu. Hal- :set +mhal tersebut adalah singkatan untuk konstruksi :{ kode multiline :}.

Whitespace juga signifikan dalam blok, jadi Anda harus membuat indentasi definisi fungsi Anda setelah definisi tipe Anda dengan empat spasi untuk memperhitungkan empat ruang dalam let.

adrian
sumber
5
Sangat sederhana, tetapi tidak jelas. Saya ingin berteriak pada buku yang saya gunakan untuk tidak memberi tahu saya bahwa pada halaman 1!
Tim
2
Dari shell Linux, echo ':set +m' >> ~/.ghciuntuk membuat pengaturan ini gigih.
truthadjustr
Anda dapat memiliki letdengan sendirinya di baris pertama maka semua yang lain tidak perlu di-indentasi sama sekali. di mana spasi putih benar-benar diperhitungkan adalah tidak boleh ada spasi tambahan di baris Anda. trailing whitespace dianggap sebagai Enter ekstra dan memecah blok multi-line.
Will Ness
14

Gunakan let:

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

Pada GHCI versi 8.0.1 , lettidak lagi diperlukan untuk mendefinisikan fungsi pada REPL.

Jadi ini seharusnya bekerja dengan baik untuk Anda:

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

Jenis-inferensi Haskell menyediakan pengetikan umum yang juga berfungsi untuk mengapung:

λ: addTwo 2.0 1.0
3.0

Jika Anda harus memberikan pengetikan sendiri, sepertinya Anda harus menggunakan letkombinasi dengan input multiline (gunakan :set +muntuk mengaktifkan input multiline di GHCI):

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

Tetapi Anda akan mendapatkan kesalahan jika Anda mencoba untuk melewatkan sesuatu selain Intkarena Anda mengetik non-polimorfik:

λ: 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
Aaron Hall
sumber
2

Untuk memperluas jawaban Aaron Hall , dalam versi GHCi 8.4.4 setidaknya, Anda tidak perlu menggunakan letdeklarasi ketik jika Anda menggunakan :{ :}style. Ini berarti Anda tidak perlu khawatir tentang menambahkan lekukan 4-ruang pada setiap baris berikutnya untuk diperhitungkan let, membuat fungsi yang lebih lama lebih mudah untuk diketik, atau dalam banyak kasus, salin-tempel (karena sumber aslinya kemungkinan tidak akan memiliki indentasi yang benar):

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

Memperbarui

Sebagai alternatif, Anda dapat mengaktifkan mode input multi-garis :set +m, lalu mengetik letsendiri, tekan Enter, lalu tempel definisi tanpa lekukan yang diperlukan.

Namun ini sepertinya tidak berfungsi dengan beberapa blok kode, seperti:

class Box a where
  mkBox :: a -> Boxes.Box

Namun :{, :}tekniknya memang demikian.

davidA
sumber
1
sebenarnya, bahkan sebelumnya, Anda bisa mengetik :{, lalu pada baris berikutnya letdengan sendirinya, lalu tempel definisi Anda tanpa lekukan tambahan apa pun, lalu tutup :}. :) dan dengan set mode input multi-line ( :set +m) Anda bahkan tidak memerlukan perintah kawat gigi selama tidak ada spasi tambahan pada baris kode.
Will Ness
Ah, jadi dengan :set +mAnda hanya dapat menggunakan letjalurnya sendiri? Jadi Anda bisa - itu keren. Terima kasih.
davidA
Hmm, saya telah menemukan beberapa kasus di mana cukup mengetik letmaka baris baru tidak berfungsi. Lihat hasil edit saya.
davidA