问题描述
,和。
我的问题是 - 是否可以在Clojure中执行Free Monad?
My question is - is it possible to do the Free Monad in Clojure?
示例:
data Free f r = Free (f (Free f r)) | Pure r
这是相应的Scala示例
This is the corresponding Scala example
sealed abstract class Free[S[+_], +A](implicit S: Functor[S]) {
final def map[B](f: A => B): Free[S, B] =
flatMap(a => Return(f(a)))
final def flatMap[B](f: A => Free[S, B]): Free[S, B] = this match {
case Gosub(a, g) => Gosub(a, (x: Any) => Gosub(g(x), f))
case a => Gosub(a, f)
}
...
}
推荐答案
是的,按照Luis Casillas的回答,这里是clojure中 Free
monad in clojure中的一个实现。
Yes, following Luis Casillas answer, here is an implementation in clojure of the Free
monad in clojure.
(use 'clojure.algo.monads)
;; data Free f r = Free (f (Free f r)) | Pure r
(defn pure [v] {:t :pure :v v})
(defn impure [v] {:t :impure :v v })
(defn free-monad
[fmap]
(letfn [
(fm-result [v] (pure v))
(fm-bind [mv mf]
(if (= :pure (:t mv))
(mf (:v mv)) ;; Pure a >>= f = f a
(impure ;; Free fa >>= f = Free (fmap (>>=f) fa)
((fmap (fn [lmv] (fm-bind lmv mf))) (:v mv)))))
]
{
:m-result fm-result
:m-bind fm-bind
:m-zero ::undefined
:m-plus ::undefined
}
)
)
=http://www.haskellforall.com/2012/06/you-could-have-invented-free-monads.html =nofollow>为什么自由monads重要:
And an example from Why free monads matter:
玩具语言的定义。
;; Toy language
;;
(defn output [c n] [{:t :output :v c}, n])
(defn bell [n] [{:t :bell}, n])
(defn done [] [{:t :done}, nil])
(defn toy-fmap [f]
(fn [[e c]]
(if (= :done (:t e))
[e c]
[e (f c)]
))
)
玩具语言+帮助函数的monad定义
Definition of the monad for the toy language + helper functions
;;
(def tt-monad
(free-monad toy-fmap))
(defn liftF [toy]
(impure ((toy-fmap (fn [c] (pure c))) toy))
)
(defn m-output [x] (liftF (output x nil)))
(defn m-bell [] (liftF (bell nil)))
(defn m-done [] (liftF (done)))
(defn f-m-done [_] (m-done))
并检查一些规则:
;; return "a" >>= output is Free(Output "a", ())
;; {:t :impure, :v [{:t :output, :v \a} {:t :pure, :v nil}]}
(with-monad tt-monad
(m-bind (m-result \a) m-output)
)
;; output "a" >>= return is Free(Output "a", ())
;; {:t :impure, :v [{:t :output, :v \a} {:t :pure, :v nil}]}
(with-monad tt-monad
(m-bind (m-output \a) m-result)
)
;; ((output 'A' >> done) >> output 'C')
(with-monad tt-monad
(m-bind (m-bind (m-output \a) f-m-done) (fn [_] (m-output \c))))
;;(output 'A' >> (done >> output 'C')) is output 'A' Done
(with-monad tt-monad
(m-bind (m-output \a) (fn [x] (m-bind (m-done) (fn [_] (m-output \c))))))
在数据结构的可读性方面改进了很多。
评论和改进最受欢迎。
This could be improved quite a lot in terms of readability of the data structure.Comments and improvements most welcome.
这篇关于有可能做Clojure中的自由Monad吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!