GHCi'de çok satırlı komutlar


135

Ghci'ye çok satırlı komutları girmede sorun yaşıyorum.

Aşağıdaki 2 satırlı kod bir dosyadan çalışır:

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

Ama ghci'ye girdiğimde bir hata alıyorum:

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

Ayrıca kodu içine koymayı da denedim :{ ... :}, ancak bu örnek için de çalışmıyorlar, çünkü bu sadece satırları bir satıra eklemek, ki durum böyle olmamalı.

WinGHCi, sürüm 2011.2.0.1 kullanıyorum


Yanıtlar:


184

Çoğu zaman, sizin için bir imza oluşturmak için tür çıkarımına güvenebilirsiniz. Örneğinizde aşağıdakiler yeterlidir:

Prelude> let addTwo x y = x + y

Gerçekten tip imzalı bir tanım istiyorsanız veya tanımınız birden fazla satıra yayılıyorsa, bunu ghci'de yapabilirsiniz:

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

Bunu bir satıra da sıkıştırabileceğinizi unutmayın:

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

Ghci ile etkileşim hakkında daha fazla bilgiyi dokümantasyonun bilgi istemi bölümünde Etkileşimli değerlendirme bölümünde bulabilirsiniz.


1
Her iki çözüm için çok teşekkürler. Ama ilgili başka bir sorum var: neden ikinci satırda (addTwo'dan önce) dört boşluk gerekiyor? Ve bu kesin olmalıdır, eğer daha az veya daha fazla boşluk varsa, o zaman bir hata vardır.
R71

9
@Rog letbir blok başlatır; bir bloktaki girişler girintiye göre gruplanır; ve bir bloktaki ilk boşluk olmayan karakter gruplandırıldıkları girintiyi ayarlar. Olmayan ilk boşluk karakteri yana letbloğun üzerinde abir addTwoblok tüm hatlar derin olduğu tam olarak girintili olarak a.
Daniel Wagner

Teşekkürler. Bunu diğer let / nerede bloklarında da fark ettim. Bu, boşlukların göz ardı edildiği diğer dillerden büyük bir farktır, bu yüzden bunu kavramakta biraz zorlandım.
R71

125

GHCI'yi çalıştırıp yazarak bu sorunu çözün :set +m:

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

Boom.


Burada neler oluyor (ve çoğunlukla konuşuyorum size yolunuzu çalışırken kişinin yardım için googling, A Haskell bilgi ) GHCI sinek işlev adlarının bağlamaları değiştirirken interaktif bir ortam olmasıdır. letHaskell'in bir şeyi tanımlamak üzere olduğunuzu anlaması için fonksiyon tanımlarınızı bir bloğa sarmanız gerekir . :set +mŞeyler satırlı için kısaltmadır :{ kod :} yapısının.

Boşluk, bloklarda da önemlidir, bu nedenle, içindeki dört boşluğu hesaba katmak için, tür tanımınızdan sonra işlev tanımınızı dört boşlukla girmeniz gerekir let.


5
Çok basit ama açık değil. 1. sayfada söylemediğim için kullandığım kitaba bağırmak istedim!
Tim

2
echo ':set +m' >> ~/.ghciBu ayarı kalıcı hale getirmek için bir Linux kabuğundan .
truthadjustr

tek letbaşına ilk satıra sahip olabilirsiniz, sonra geri kalan her şeyin girintili olmasına gerek yoktur. boşluk gerçekten önemliyse, satırlarınızın sonunda boşluk olmamalıdır. sondaki boşluk fazladan bir Enter olarak sayılır ve çok satırlı bloğu bozar.
Will Ness

14

Kullanım let:

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

5

İtibariyle GHCI sürümü 8.0.1 , letartık repl işlevleri tanımlamak için gereklidir.

Yani bu sizin için iyi çalışmalı:

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

Haskell'in tür çıkarımı, float'lar için de işe yarayan genelleştirilmiş yazım sağlar:

λ: addTwo 2.0 1.0
3.0

Kendi yazımınızı sağlamanız gerekiyorsa let, çok satırlı girişle birlikte kullanmanız gerekecek gibi görünüyor ( :set +mGHCI'de çok satırlı girişi etkinleştirmek için kullanın ):

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

Ancak Intpolimorfik olmayan yazmanız nedeniyle herhangi bir şeyi iletmeye çalışırsanız hatalar alırsınız :

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

2

Aaron Hall'un cevabını genişletmek için , en azından GHCi 8.4.4 sürümünde let, :{ :}stili kullanıyorsanız tip bildirimleriyle birlikte kullanmanıza gerek yoktur . Bu, hesaba katmak için sonraki her satıra 4 boşluk girintisi ekleme, daha letuzun işlevlerin yazılmasını çok daha kolay hale getirme veya çoğu durumda kopyalayıp yapıştırma konusunda endişelenmenize gerek olmadığı anlamına gelir (orijinal kaynak büyük olasılıkla doğru girinti):

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

Güncelleme

Alternatif olarak ile çok satırlı giriş modunu açabilir :set +m, ardından letkendi başına yazabilir , Enter tuşuna basabilir ve ardından tanımları girinti gerektirmeden yapıştırabilirsiniz.

Ancak bu, aşağıdaki gibi bazı kod bloklarıyla çalışmıyor gibi görünüyor:

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

Ancak :{, :}teknik yapar.


1
aslında, daha önce bile :{, yazıp sonraki satıra letkendi başına yazabilir , sonra tanımlarınızı hiçbir girinti eklemeden yapıştırabilir ve ardından kapatabilirsiniz :}. :) ve çok satırlı giriş modu set ( :set +m) ile, kod satırlarının sonunda boşluk olmadığı sürece küme ayracı komutlarına bile ihtiyacınız yoktu.
Will Ness

Ah, yani birlikte :set +msize sadece kullanabilirsiniz letkendi satırında? Böylece yapabilirsiniz - bu harika. Teşekkür ederim.
Davida

Hmm, basitçe letyeni satırı yazmanın işe yaramadığı bazı durumlar buldum . Düzenlememe bakın.
Davida
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.