Soru İfadeler için 'veya' için Haskell sözdizimi


F # 'da kullanabilirim | örüntü eşleştiğinde durumları gruplandırmak. Örneğin,

let rec factorial n = 
  match n with
  | 0 | 1 -> 1                 // like in this line
  | _ -> n * factorial (n - 1)

Aynı Haskell sözdizimi nedir?


25
2017-09-29 21:19


Menşei


Görmek Haskell 2010> İfadeler # Vaka İfadeleri Haskell'in davasının resmi açıklaması için. - Dan Burton
Bu desteklenmedi (henüz), ancak bkz. haskell.org/haskellwiki/MultiCase sözdizimi teklifi için - hvr
Hvr ile bağlantılı sözdizimi teklifinin bu StackOverflow sorusuna doğrudan yanıt verdiğini unutmayın. ;) - Dan Burton
Muhafızlarla belirtildiği gibi. Tedavi edebilirsin | sembol gibi when F # anahtar sözcük. - MasterMastic


Cevaplar:


Farklı modeller için aynı sağ tarafı paylaşmanın hiçbir yolu yoktur. Bununla birlikte, genellikle desen yerine korumaları kullanarak bunu yapabilirsiniz. elem.

foo x | x `elem` [A, C, G] = ...
      | x `elem` [B, D, E] = ...
      | otherwise          = ...

28
2017-09-29 22:22



Muhafızların kullanılması, denklemlerin doğru tarafını paylaşmaya nasıl yardımcı olur? - jmg
Posterin senaryosu şöyle olurdu: | x elem [0,1] = 1 - Jimmy Hoffa


muhafızlarla:

factorial n
    | n < 2 = 1
    | otherwise = n * (factorial (n - 1))

desen eşleme ile:

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

9
2017-09-29 21:25



Bir kaç durumda, belirli bir ayda gün sayısı çıkarılmak gibi bir şey varsa ne olur? - Rahul Göma Phuloré


F # ile tam olarak tanıdık değilim, ama Haskell'de, durum ifadeleri desen eşlemesine izin verir, değişkenleri bir ifadenin bölümlerine bağlar.

case listExpr of
    (x:y:_) -> x+y
    [x]     -> x
    _       -> 0

Haskell'in de aynı şekilde izin verdiği teorik olayda:

Bu nedenle birden çok bağlamaya izin vermek sorunlu olurdu

case listExpr of
    (x:y:_) | [z] -> erm...which variables are bound? x and y? or z?

Aynı bağlamayı kullanarak çalışabileceği nadir durumlar vardır:

 unEither :: Either a a -> a
 unEither val = case val of
   Left v | Right v -> v

Ve verdiğiniz örnekte olduğu gibi, sadece harflerle eşleşirseniz ve hiçbir şeyi bağlamazsanız, iyi çalışabilir:

case expr of
  1 | 0 -> foo
  _     -> bar

Ancak:

Bildiğim kadarıyla, Haskell'in böyle bir sözdizimi yok. Diğerleri tarafından da belirtildiği gibi, muhafızları var.

Ayrıca not:

kullanma | Davada Haskell'de farklı bir işlev görür. Sonrası ifadesi | bir bekçi olarak davranır.

case expr of
  [x] | x < 2 -> 2
  [x] -> 3
  _ -> 4

Bu tür bir sözdizimi Haskell'e tanıtılacak olsaydı, bunun dışında bir şey kullanmak zorunda kalacaktı. |. Kullanmanızı öneririm , (bunu Haskell speklerine eklemek gibi hissedebilirsiniz)

unEither val = case val of
  Left v, Right v -> v

Bu, şu anda "girişte ayrıştırma hatası" üretiyor ,"


6
2017-09-30 00:19



"hangi değişkenler bağlı? x ve y? veya z?" OCaml ve F # 'da aynı bağlamaları tam olarak bağlamak için her bir desen gerektirir - newacct
@newacct cool. Teorimi tanımak güzeldi doğru yolda. Bunu, Haskell'e dahil etmenin çok zor olacağını hayal edemiyorum, bu yüzden henüz neden olmadıklarına dair hiçbir fikrim yok. - Dan Burton
Çalışılacak "nadir" olaylar, anlamlı olan bu oluşumlardır - aslında yazdığımızın sonu. Yani "nadir" burada korkunç derecede küçültücü değildir. Ancak, pratik şartlarda şüpheleniyorum, yazım denetimi için bir sorun teşkil ediyor çünkü vmonomorfik olarak bağlanmalıdır ve bu durumlarda RHS'nin polimorfik olarak tipine bağlı olduğundan şüpheleniyorum. v. Gerçek kaynak kodunu analiz etmeden emin değilim. - luqui
@luqui Nadir görülmesi gereken yerlerde, istediğiniz şeyi elde etmek için kayıt seçici sözdizimini kullanabilirsiniz? Yani, her zaman aynı inşa eden aynı kurucu alanlarla aynı mıdır, yoksa bazen (kurucu bir, bir alan, kurucu iki, bir alan) ve bazen de (kurucu bir, alan bir, kurucu iki) alan iki)? - Daniel Wagner


Yukarıdaki cevaplardan bazılarına dayanarak, (en azından şimdi) tek bir satıra birden fazla vaka yapmak için gardiyanları kullanabilirsiniz:

case name of
    x | elem x ["Bob","John","Joe"] -> putStrLn "ok!"
    "Frank"                         -> putStrLn "not ok!"
    _                               -> putStrLn "bad input!"

Yani, "Bob", "John" veya "Joe" nun bir girişi size "tamam" verirken "Frank" "tamam olmaz!" Ve diğer her şey "kötü girdi" olur.


6
2017-09-04 18:55





İşte oldukça basit bir çeviri:

factorial n = case n of
    0 -> sharedImpl
    1 -> sharedImpl
    n -> n * factorial (n - 1)
    where
        sharedImpl = 1

Görünüm kalıpları da size gerçek bir çeviri sağlayabilir.

isZeroOrOne n = case n of
    0 -> True
    1 -> True
    _ -> False

factorial1 n = case n of
    (isZeroOrOne -> True) -> 1
    n -> n * factorial (n - 1)

factorial2 n = case n of
    (\n -> case n of { 0 -> True; 1 -> True; _ -> False }) -> 1
    n -> n * factorial (n - 1)

Bunların alternatiflerden daha iyi olduğunu söylemiyorum. Sadece onları işaret ederek.


3
2018-04-15 18:03



Evet! "Sadece o şeyi adlandır"! Böyle bir söz olmalı, değil mi? :) Bu arada, bir zamanlar diğer akıllı türlerden insanları gerçekten ayıran şeyin (aynaya bakma değil) olduğunu duydum. puan: "görmek, o!". :) - Will Ness