Serbest değişkenleri tarafından parametrelendirilen lambda terimleri için bu gösterimi düşünün. (Bellegarde ve Hook 1994, Bird ve Paterson 1999, Altenkirch ve Reus 1999'un makalelerine bakın.)
data Tm a = Var a
| Tm a :$ Tm a
| Lam (Tm (Maybe a))
Bunu kesinlikle Functor
yeniden adlandırma Monad
fikrini ve ikame kavramını yakalayan bir hale getirebilirsiniz .
instance Functor Tm where
fmap rho (Var a) = Var (rho a)
fmap rho (f :$ s) = fmap rho f :$ fmap rho s
fmap rho (Lam t) = Lam (fmap (fmap rho) t)
instance Monad Tm where
return = Var
Var a >>= sig = sig a
(f :$ s) >>= sig = (f >>= sig) :$ (s >>= sig)
Lam t >>= sig = Lam (t >>= maybe (Var Nothing) (fmap Just . sig))
Şimdi kapalı şartları düşünün : bunlar sakinleridir Tm Void
. Kapalı terimleri rastgele serbest değişkenler içeren terimlere yerleştirebilmelisiniz. Nasıl?
fmap absurd :: Tm Void -> Tm a
İşin püf noktası, elbette, bu işlevin hiçbir şey yapmadan terimi aşacak olmasıdır. Ama daha dürüst bir dokunuş unsafeCoerce
. Ve bu yüzden vacuous
eklendi Data.Void
...
Veya bir değerlendirici yazın. Serbest değişkenli değerler burada b
.
data Val b
= b :$$ [Val b]
| forall a. LV (a -> Val b) (Tm (Maybe a))
Lambdaları kapanışlar olarak temsil ettim. Değerlendirici, serbest değişkenleri a
üzerinden değerlere eşleyen bir ortam tarafından parametrelendirilir b
.
eval :: (a -> Val b) -> Tm a -> Val b
eval g (Var a) = g a
eval g (f :$ s) = eval g f $$ eval g s where
(b :$$ vs) $$ v = b :$$ (vs ++ [v])
LV g t $$ v = eval (maybe v g) t
eval g (Lam t) = LV g t
Tahmin ettin. Herhangi bir hedefte kapalı bir terimi değerlendirmek için
eval absurd :: Tm Void -> Val b
Daha genel olarak, Void
nadiren kendi başına kullanılır, ancak bir çeşit imkansızlığı gösteren bir şekilde bir tür parametresini somutlaştırmak istediğinizde kullanışlıdır (örneğin burada, kapalı bir terimde serbest bir değişken kullanarak). Genellikle bu parametrized tipleri daha yüksek dereceden fonksiyonlar bütün türüne operasyonlara parametrelere kaldırma işlemlerindeki ile gelen (örneğin, burada, fmap
, >>=
, eval
). Yani absurd
genel amaçlı operasyon olarak geçiyorsunuz Void
.
Başka bir örnek için, Either e v
size bir v
tür istisnası getirebileceğini umduğumuz hesaplamaları yakalamak için kullanmayı hayal edin e
. Kötü davranış riskini aynı şekilde belgelemek için bu yaklaşımı kullanabilirsiniz. Gayet iyi bu ayarda hesaplamaları davranmış için almak e
olmaya Void
ardından kullanımını
either absurd id :: Either Void v -> v
güvenle koşmak veya
either absurd Right :: Either Void v -> Either e v
güvenli bileşenleri güvenli olmayan bir dünyaya yerleştirmek.
Oh, ve son bir ani bir "olamaz" ı ele almak. İmlecin olamayacağı her yerde jenerik fermuar yapısında ortaya çıkıyor.
class Differentiable f where
type D f :: * -> *
plug :: (D f x, x) -> f x
newtype K a x = K a
newtype I x = I x
data (f :+: g) x = L (f x)
| R (g x)
data (f :*: g) x = f x :&: g x
instance Differentiable (K a) where
type D (K a) = K Void
plug (K v, x) = absurd v
Tam olarak alakalı olmasa da geri kalanını silmemeye karar verdim.
instance Differentiable I where
type D I = K ()
plug (K (), x) = I x
instance (Differentiable f, Differentiable g) => Differentiable (f :+: g) where
type D (f :+: g) = D f :+: D g
plug (L df, x) = L (plug (df, x))
plug (R dg, x) = R (plug (dg, x))
instance (Differentiable f, Differentiable g) => Differentiable (f :*: g) where
type D (f :*: g) = (D f :*: g) :+: (f :*: D g)
plug (L (df :&: g), x) = plug (df, x) :&: g
plug (R (f :&: dg), x) = f :&: plug (dg, x)
Aslında, belki alakalı. Kendinizi maceraperest hissediyorsanız, bu bitmemiş makale , Void
terimlerin temsilini serbest değişkenlerle nasıl sıkıştıracağınızı gösterir.
data Term f x = Var x | Con (f (Term f x))
a Differentiable
and Traversable
functor'dan serbestçe üretilen herhangi bir sözdiziminde f
. Kullandığımız Term f Void
serbest değişkenlerle bölgeleri temsil etmek ve [D f (Term f Void)]
göstermek için boruları izole edilmiş bir serbest değişkene, ya da iki ya da daha fazla serbest değişkenlere yollarında bir birleşme ya serbest değişkenlerle bölgeleri ile tünel. Bu makaleyi bir ara bitirmelisin.
Değeri olmayan bir tür için (veya en azından kibar bir şirkette konuşmaya değmez), Void
oldukça kullanışlıdır. Ve absurd
bunu nasıl kullandığın.
absurd
işlevin bu makaledeCont
monad ile ilgili olarak kullanıldığını gösteriyor : haskellforall.com/2012/12/the-continuation-monad.html