Bu iki parçacığın neden sözde "yoksul adamın sıkılık analizi" altında farklı sonuçlar ürettiğini anlamak için uğraşıyorum.Veri ve yeni tip arasındaki boşluk/sıkılık
ilk örneği data
(doğru bir Uygulamalı örnek varsayılarak) kullanır:
data Parser t a = Parser {
getParser :: [t] -> Maybe ([t], a)
}
> getParser (pure (,) <*> literal ';' <*> undefined) "abc"
*** Exception: Prelude.undefined
ikinci newtype
kullanır. Başka bir fark yoktur:
newtype Parser t a = Parser {
getParser :: [t] -> Maybe ([t], a)
}
> getParser (pure (,) <*> literal ';' <*> undefined) "abc"
Nothing
literal x
onun argümanı ilk belirteci eşleşirse girişinin bir belirteci tüketen başarır bir ayrıştırıcısıdır. Yani bu örnekte, ;
bu yana a
eşleşmiyor. Ancak, data
örnek hala sonraki ayrıştırıcının tanımsız olduğunu görür, newtype
örnek yapmaz.
this, this ve this'u okudum, ancak ilk örneklerin neden tanımlanmadığını anlamak için onları yeterince iyi anlamıyorum. Bana öyle geliyor ki, bu örnekte, newtype
, data
numaralı telefondan daha tembeldir, cevapların tam tersi. (En az one other person da bununla karıştırılmıştır).
data
'dan newtype
'a geçiş neden bu örneğin tanımını değiştiriyor?
Burada keşfedilen bir şey Bu Uygulamalı örneğiyle, çıkışlar üzerinde data
ayrıştırıcı tanımlanmamış: Bu örnek ile, data
ayrıştırıcı üzerinde, buna karşın
instance Applicative (Parser s) where
Parser f <*> Parser x = Parser h
where
h xs =
f xs >>= \(ys, f') ->
x ys >>= \(zs, x') ->
Just (zs, f' x')
pure a = Parser (\xs -> Just (xs, a))
tanımsız olup çıkışı (varsayarak (için doğru bir Monad örneği):
instance Applicative (Parser s) where
f <*> x =
f >>= \f' ->
x >>= \x' ->
pure (f' x')
pure = pure a = Parser (\xs -> Just (xs, a))
Tam kod parçacığı:
import Control.Applicative
import Control.Monad (liftM)
data Parser t a = Parser {
getParser :: [t] -> Maybe ([t], a)
}
instance Functor (Parser s) where
fmap = liftM
instance Applicative (Parser s) where
Parser f <*> Parser x = Parser h
where
h xs = f xs >>= \(ys, f') ->
x ys >>= \(zs, x') ->
Just (zs, f' x')
pure = return
instance Monad (Parser s) where
Parser m >>= f = Parser h
where
h xs =
m xs >>= \(ys,y) ->
getParser (f y) ys
return a = Parser (\xs -> Just (xs, a))
literal :: Eq t => t -> Parser t t
literal x = Parser f
where
f (y:ys)
| x == y = Just (ys, x)
| otherwise = Nothing
f [] = Nothing
Böyle bir soru sorulduğunda, tüm ilgili kodları eklediğinizde, eğer sığacak kadar küçükse (bu "Functor" ve "Monad" örneklerini ve "literal" içerir), böylece insanlar Fonksiyonları tam olarak nasıl yazdığınızı tahmin etmelisiniz (belirttiğiniz gibi, küçük değişiklikler bile davranışlarda fark yaratabilir). – shachaf
@shachaf asıl soru burada "kodumu nasıl düzeltirim?" - Bunu zaten yaptım - ama “veri” ile “yeni tip” arasındaki farklılık, katılık/tembellik açısından farklı mı? ” Maalesef bu sorudan belli değil. –
Evet, ama yine de, kodun neye benzediğini bilmeden kodunuzda neler olduğunu nasıl açıklayabiliriz? – shachaf