它可能代表幾乎任何你想要的類型。但是,由於每種類型的一元操作的實施方式不同,因此可以將而不是寫入>>=
一次,並使其適用於每個實例。
但是,您可以可以編寫依賴於類型類實例的證據的通用函數。考慮這裏的e
是一個元組,其中fst e
包含「綁定」定義,並且snd e
包含「返回」定義。
bind = λe. fst e -- after applying evidence, bind looks like λmf. ___
return = λe. snd e -- after applying evidence, return looks like λx. ___
fst = λt. t true
snd = λt. t false
-- join x = x >>= id
join = λex. bind e x (λz. z)
-- liftM f m1 = do { x1 <- m1; return (f x1) }
-- m1 >>= \x1 -> return (f x1)
liftM = λefm. bind e m (λx. return e (f x))
你將不得不定義一個「證據元組」的單子的每個實例。請注意,在路上,我們定義bind
和return
:他們的工作就像其他「通用」單子我們定義的方法:他們首先必須得到單子岬的證據,然後他們按預期。
我們可以表示Maybe
作爲需要2個輸入的函數,第一個是執行,如果它是Just x
一個函數,第二個是與如果是沒有替換它的值。
just = λxfz. f x
nothing = λfz. z
-- bind and return for maybes
bindMaybe = λmf. m f nothing
returnMaybe = just
maybeMonadEvidence = tuple bindMaybe returnMaybe
列表相似,代表List作爲其摺疊功能。因此,列表是一個函數,需要2個輸入,一個「缺點」和一個「空白」。然後它在列表上執行foldr myCons myEmpty
。
nil = λcz. z
cons = λhtcz. c h (t c z)
bindList = λmf. concat (map f m)
returnList = λx. cons x nil
listMonadEvidence = tuple bindList returnList
-- concat = foldr (++) []
concat = λl. l append nil
-- append xs ys = foldr (:) ys xs
append = λxy. x cons y
-- map f = foldr ((:) . f) []
map = λfl. l (λx. cons (f x)) nil
Either
也很簡單。將任一類型表示爲具有兩個功能的函數:如果它是Left
,則應用一個;如果是Right
,則應用另一個類型。
left = λlfg. f l
right = λrfg. g r
-- Left l >>= f = Left l
-- Right r >>= f = f r
bindEither = λmf. m left f
returnEither = right
eitherMonadEvidence = tuple bindEither returnEither
不要忘記,職能自己(a ->)
形式的單子。而lambda演算中的所有內容都是一個函數......所以......不要太想它。 ;)直接從啓發的Control.Monad.Instances
-- f >>= k = \ r -> k (f r) r
bindFunc = λfkr. k (f r) r
-- return = const
returnFunc = λxy. x
funcMonadEvidence = tuple bindFunc returnFunc
源由於lambda演算是圖靈完成它能夠編碼任何計算過程中它。我想這個問題正是關於編碼。當然,非類型化的微積分類型中沒有類型,但可以編碼一些表現爲類型和鍵入機制的對象。與沒有bool和數字的方式相同,但在問題中引用了相應的編碼。 [Dan回答](https://stackoverflow.com/a/8936209/707926)更符合這種理解。 –