Birden fazla satırda ghci'de bir işlev nasıl tanımlanır?


161

Ghci birden fazla satır yayılan herhangi bir basit işlevi tanımlamak çalışıyorum, aşağıdaki örnek alın:

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

Şimdiye kadar ilk satırdan sonra Enter tuşuna basmayı denedim:

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

Ayrıca :{ve :}komutlarını kullanmaya çalıştım ama çok uzağa gitmiyorum:

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

Linux'ta Haskell 98 için GHC Interactive sürüm 6.6 kullanıyorum, ne eksik?


20
Lütfen GHC kurulumunuzu yükseltin. GHC 6.6 neredeyse 5 yaşında! Haskell'in en son sürümleri burada: haskell.org/platform
Don Stewart


1
@ Mark Bu OP zaten bu sorunun çözümlerini denedi. Bu sorun, ne yapılacağı konusunda bilgi eksikliğinden değil, güncel olmayan bir ghci'den kaynaklanmaktadır. Burada çözüm: yükseltme. Orada Çözüm: kullanım :{, :}.
AndrewC

Yanıtlar:


124

Muhafızlar için (örneğin örnek olarak) hepsini tek bir satıra koyabilirsiniz ve işe yarar (muhafızlar aralıklarla ilgilenmez)

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

İşlevinizi, aşağıdaki gibi bağımsız değişkenlerle eşleşen çoklu tanımlarla yazmak istiyorsanız, şöyle:

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

Sonra noktalı virgüllerle tanımları ayıran parantez kullanırsınız

let { fact 0 = 1 ; fact n = n * fact (n-1) }

258

GHCi artık set + m ile etkinleştirilen çok satırlı giriş moduna sahip. Örneğin,

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

39
Çok satırlı modun ayarlanması ghci, bu bağlamda Python yorumlayıcısı gibi davranır. Çok uygun! Aslında .ghci, giriş dizininizde koyduğunuz bir dosya oluşturabilirsiniz :set +mve çok satırlı mod her başladığınızda varsayılan olur ghci!
kqr

2
Bu gerçekten harika. Ama kullanarak istemi ayarladığınızda fark etmiş :set prompt "λ "devamı çizgiler demek Preludeyerine λ. Bunu aşmanın bir yolu var mı?
abhillman

2
Yeni bir devam istemi tanımlamak için düzeltme eki için buraya bakın ghc.haskell.org/trac/ghc/ticket/7509#no1
karakfa

4
Prelude'un devam satırlarında görünmesini önlemek için, şunu da ekleyin: .ghci'nizde prompt2 "|" ayarlayın.
Nick

12
Sen edebilir tamamen bir sondaki kullanarak girinti kaçının let. Basitçe a ve letardından bir satırsonu yazın: let⏎. Sonra fac 0 = 1⏎. Sonra fac n = n * fac (n-1)⏎ ⏎ ve işiniz bitti!
Iceland_jack

62

Dan doğru ama :{ve :}her biri kendi satırında yer almalıdır:

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

Bu, düzen kuralıyla da etkileşime girer, bu nedenle do-notasyonunu kullanırken diş telleri ve noktalı virgüllerin açıkça kullanılması daha kolay olabilir. Örneğin, bu tanım başarısız olur:

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

Ancak diş telleri ve noktalı virgüller eklendiğinde çalışır:

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

Bu, yalnızca girintinin değişebileceği bir dosyadan tanımları yapıştırırken gerçekten önemli olacaktır.


En azından 7.6.3 sürümünde '=' ile biten bir satırınız varsa (sonraki satırda aşağıdaki tanımla birlikte) bir satırınız varsa bu çalışmaz.
AdamC

1
Belki de bu başarısız olur, çünkü izin ikinci ve üçüncü satırı yeterince girintili değildir…? (İki boşluk daha.)
Evi1M4chine


7

GHC'yi yalnızca için yükseltmek istemiyorsanız :{ve :}hepsini bir satıra yazmanız gerekir:

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

Haskell'de birden çok satıra yazılması gereken tek bir tanımın farkında değilim . Yukarıdakiler gerçekten GHCi'de çalışıyor:

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

doBloklar gibi diğer ifadeler için, düz olmayan sözdizimini kıvırcık parantez ve noktalı virgüllerle (eugh) kullanmanız gerekir.


0

MacOS Catalina 10.15.2 üzerinde GHCi, sürüm 8.2.1 kullanıyorum. Aşağıda hem işlev türü bildirimini hem de korumaları bir araya getirdim. Soldaki dikey çubukların birden fazla satır için olduğunu unutmayın.

λ: let abs' :: (Num a, Ord a) => a -> a
 |     abs' n | n >= 0 = n | otherwise = -n
 | 
λ: abs' 7
7
λ: abs' (-7)
7

1
Kullanırsanız :{ve tür bildiriminizden önce :}belirtmeniz let gerekmiyorsa, ikinci ve sonraki satırları girintilemeniz gerekmez.
davidA

Çok teşekkür ederim davidA. Tam da aradığım şey bulamadı ama bulamadım.
Altın Başparmak

0

Her iki satırı aynı anda yapıştırmak veya her yeni satır için control-enter kullanmak, en azından https://repl.it/languages/haskell adresinde hepsini bir arada tutar . İkinci satırın başında 2 nokta göreceksiniz. Veya bir dosyaya koyun ve: dosyayı yükleyin (: l main). Neden abs negatif sayılarla çalışmıyor? Ah sayının etrafına parantez koymalısınız.

   let abs n | n >= 0 = n 
..           | otherwise = -n
   abs (-1)
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.