พิจารณาการแทนค่านี้สำหรับคำศัพท์แลมบ์ดาที่กำหนดโดยตัวแปรอิสระ (ดูเอกสารของ Bellegarde and Hook 1994, Bird and Paterson 1999, Altenkirch และ Reus 1999)
data Tm a = Var a
| Tm a :$ Tm a
| Lam (Tm (Maybe a))
คุณสามารถสร้างสิ่งนี้ได้อย่างแน่นอนFunctor
โดยจับความคิดของการเปลี่ยนชื่อและMonad
จับความคิดของการแทนที่
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))
ตอนนี้พิจารณา ปิดTm Void
เงื่อนไขเหล่านี้เป็นที่อาศัยอยู่ใน คุณควรจะสามารถฝังคำที่ปิดลงในเงื่อนไขที่มีตัวแปรอิสระตามอำเภอใจ อย่างไร?
fmap absurd :: Tm Void -> Tm a
แน่นอนว่าสิ่งที่จับได้คือฟังก์ชันนี้จะข้ามผ่านคำที่ทำอะไรไม่ได้อย่างแม่นยำ unsafeCoerce
แต่มันเป็นสัมผัสเที่ยงตรงมากกว่า และนั่นคือสาเหตุที่vacuous
ถูกเพิ่มเข้าไปในData.Void
...
หรือเขียนผู้ประเมิน. นี่คือค่าที่มีตัวแปรอิสระในb
.
data Val b
= b :$$ [Val b]
| forall a. LV (a -> Val b) (Tm (Maybe a))
ฉันเพิ่งเป็นตัวแทนของ lambdas เป็นปิด ประเมินเป็น parametrized โดยตัวแปรอิสระทำแผนที่สภาพแวดล้อมในการค่ามากกว่าa
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
คุณเดาได้ เพื่อประเมินระยะปิดที่เป้าหมายใด ๆ
eval absurd :: Tm Void -> Val b
โดยทั่วไปแล้วมักVoid
ไม่ค่อยมีการใช้ด้วยตัวเอง แต่มีประโยชน์เมื่อคุณต้องการสร้างอินสแตนซ์พารามิเตอร์ประเภทในลักษณะที่บ่งบอกถึงความเป็นไปไม่ได้บางประเภท (เช่นที่นี่ใช้ตัวแปรอิสระในระยะปิด) บ่อยครั้งที่ประเภท parametrized เหล่านี้มาพร้อมกับฟังก์ชันลำดับที่สูงขึ้นในการยกการดำเนินการของพารามิเตอร์ไปสู่การดำเนินการกับทั้งประเภท (เช่นที่นี่fmap
,>>=
, eval
) ดังนั้นคุณผ่านในฐานะการดำเนินงานทั่วไปที่มีวัตถุประสงค์ในการabsurd
Void
สำหรับตัวอย่างอื่นจินตนาการโดยใช้Either e v
การคำนวณจับซึ่งหวังว่าให้คุณแต่อาจจะเพิ่มข้อยกเว้นชนิดv
e
คุณอาจใช้วิธีนี้ในการบันทึกความเสี่ยงของพฤติกรรมที่ไม่ดีอย่างสม่ำเสมอ สำหรับการคำนวณที่ทำงานได้ดีอย่างสมบูรณ์แบบในการตั้งค่านี้e
ให้เป็นVoid
ใช้
either absurd id :: Either Void v -> v
เพื่อให้ทำงานได้อย่างปลอดภัยหรือ
either absurd Right :: Either Void v -> Either e v
เพื่อฝังส่วนประกอบที่ปลอดภัยในโลกที่ไม่ปลอดภัย
โอ้และอีกครั้งสุดท้ายที่รีบจัดการกับ "ไม่สามารถเกิดขึ้นได้" มันปรากฏขึ้นในโครงสร้างซิปทั่วไปทุกที่ที่เคอร์เซอร์ไม่สามารถอยู่ได้
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
ฉันตัดสินใจที่จะไม่ลบส่วนที่เหลือแม้ว่าจะไม่ตรงประเด็นก็ตาม
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)
จริงๆแล้วอาจจะมีความเกี่ยวข้อง หากคุณรู้สึกอยากผจญภัยบทความที่ยังไม่เสร็จนี้จะแสดงวิธีใช้Void
เพื่อบีบอัดการแสดงคำที่มีตัวแปรอิสระ
data Term f x = Var x | Con (f (Term f x))
ในไวยากรณ์ใด ๆ ที่สร้างได้อย่างอิสระจากDifferentiable
และfunctorTraversable
f
เราใช้Term f Void
เพื่อแสดงภูมิภาคที่ไม่มีตัวแปรอิสระและ[D f (Term f Void)]
เป็นตัวแทนท่อขุดเจาะอุโมงค์ผ่านพื้นที่ที่มีไม่มีตัวแปรอิสระทั้งตัวแปรอิสระแยกหรือทางแยกในเส้นทางถึงสองหรือตัวแปรอิสระมากขึ้น ต้องจบบทความนั้นในบางครั้ง
สำหรับประเภทที่ไม่มีค่า (หรืออย่างน้อยก็ไม่มีค่าที่จะพูดถึงใน บริษัท ที่สุภาพ) Void
จะมีประโยชน์อย่างมาก และabsurd
เป็นวิธีที่คุณใช้
absurd
มีการใช้ฟังก์ชันนี้ในบทความนี้เกี่ยวกับCont
monad: haskellforall.com/2012/12/the-continuation-monad.html