读者monad是如此复杂,似乎没用.在像Java或C++这样的命令式语言中,如果我没有弄错的话,读者monad没有相同的概念.
你能给我一个简单的例子并清楚一点吗?
如何在Scala中创建功能正常的可配置对象?我看过托尼莫里斯关于Readermonad 的视频,我仍然无法连接点.
我有一个硬编码的Client对象列表:
class Client(name : String, age : Int){ /* etc */}
object Client{
//Horrible!
val clients = List(Client("Bob", 20), Client("Cindy", 30))
}
Run Code Online (Sandbox Code Playgroud)
我希望Client.clients在运行时确定,可以灵活地从属性文件或数据库中读取它.在Java世界中,我定义了一个接口,实现了两种类型的源,并使用DI来分配一个类变量:
trait ConfigSource {
def clients : List[Client]
}
object ConfigFileSource extends ConfigSource {
override def clients = buildClientsFromProperties(Properties("clients.properties"))
//...etc, read properties files
}
object DatabaseSource extends ConfigSource { /* etc */ }
object Client {
@Resource("configuration_source")
private var config : ConfigSource = _ //Inject it at runtime
val clients …Run Code Online (Sandbox Code Playgroud) 在斯卡拉兹
Kleisli[F, A, B]是一个包装A => F[B].ReaderT[F, A, B]- 读者monad变换器 - 只是别名Kleisli[F, A, B].Reader[A, B]monad是ReaderT身份monad 的专长Id:type Reader[A, B] = ReaderT[Id, A, B].难道仅仅是巧合还是有一些更深层次的原因Kleisli,ReaderT以及Reader是同构的Scalaz?
我有以下代码使用Readermonad进行配置,还必须处理,IO[Option[String]]我最终得到的代码是我的encode函数中的阶梯.
我怎样才能为我的函数中的monad变换器制定Reader并OptionT避免丑陋的嵌套for理解encode?
def encode(fileName: String): Reader[Config, IO[Unit]] = for {
ffmpegWrapper <- findFfmpegWrapper
ffmpegBin <- findFfmpeg
} yield (for {
w <- ffmpegWrapper
b <- ffmpegBin
stream <- callFfmpeg(getCommand(w, b, fileName)).liftM[OptionT]
} yield stream) map (_ foreach (println)) getOrElse Unit.box {}
def getCommand(ffmpegWrapper: String, ffmpegBin: String,
videoFile: String) = s"$ffmpegWrapper $ffmpegBin $videoFile '-vcodec libx264 -s 1024x576' /tmp/out.mp4"
def callFfmpeg(command: String): IO[Stream[String]] = IO {
Process(command).lines_!
} …Run Code Online (Sandbox Code Playgroud) 我正在通过示例阅读Purescript并介绍了阅读Monad的部分.这个例子是这样的:
createUser :: Reader Permissions (Maybe User)
createUser = do
permissions <- ask
if hasPermission "admin" permissions
then map Just newUser
else pure Nothing
Run Code Online (Sandbox Code Playgroud)
对我来说令人困惑的部分是ask功能.签名是:
ask :: forall r. Reader r r
Run Code Online (Sandbox Code Playgroud)
它看起来好像是凭空创造了一个阅读器
当我读到Statemonad时,它的get功能与概念相同.文字解释说:
状态被实现为State monad的数据构造函数隐藏的函数参数,因此没有明确的引用传递.
我猜这是关键,同样的事情发生在这里与读者,但我不明白它是如何工作的......
当上面的例子运行时runReader,提供的值如何突然出现ask?Haskell文档ask说:检索monad环境.但我的困惑是从哪里来的?我看到它的方式,一个值传递给runReader,存储在某个地方,并得到它 - 你打电话ask......但这没有任何意义.
虽然这个例子是Purescript,但我猜测任何有Haskell识字的人也能够回答,因此Haskell标签.
用于环境共享和非确定性的规范"Monad实例"如下(使用伪Haskell,因为Haskell Data.Set当然不是monadic):
eta :: a -> r -> {a} -- '{a}' means the type of a set of a's
eta x = \r -> {x}
bind :: (r -> {a}) -> (a -> r -> {b}) -> r -> {b}
m `bind` f = \r -> {v | x ? m r, v ? f x r}
Run Code Online (Sandbox Code Playgroud)
通常,当尝试将像Powerset(List,Writer等)的"容器"monad与第二个monad m(这里,粗略地,Reader)组合时,一个'包裹' m在容器monad周围,如上所述.
那么,我想知道以下潜在的Powerset-over-Reader规范:
eta' :: a -> {r -> a}
eta' x = {\r -> x}
bind' :: {r …Run Code Online (Sandbox Code Playgroud) 只是寻找解释以下组成如何工作:
(=<<) . return
Run Code Online (Sandbox Code Playgroud)
哪里
(=<<) :: (a -> m b) -> m a -> m b
return :: a -> m a
(.) :: (b -> c) -> (a -> b) -> a -> c
Run Code Online (Sandbox Code Playgroud)
最终类型:
GHCi> :t (=<<) . return
(=<<) . return :: Monad m => m b -> m a -> m b
Run Code Online (Sandbox Code Playgroud)
我上无法掌握如何能比得上马用(A - > MB) ,即.如何将一个简单类型的返回结果应用到期望函数类型的(= <<)的第一个参数?
monads haskell type-inference function-composition reader-monad
我看过algo.monads和fluokitten文档.我还阅读了Jim Duey,Konrad Hinsen和Leonardo Borges的 monad博客文章.
我可以在Clojure中找到读者Monad的唯一参考是谷歌小组的讨论.
我的问题是:是否可以在Clojure中使用Haskell的Reader Monad?你能提供一个例子吗?
阅读http://learnyouahaskell.com/functors-applicative-functors-and-monoids#applicative-functors之后,我可以提供一个将函数用作应用函子的示例:
比方说res是4个参数和功能fa,fb,fc,fd是采取单一参数的所有功能。然后,如果我没记错的话,此适用表达式:
f <$> fa <*> fb <*> fc <*> fd $ x
Run Code Online (Sandbox Code Playgroud)
与此非特殊表达式的含义相同:
f (fa x) (fb x) (fc x) (fd x)
Run Code Online (Sandbox Code Playgroud)
啊。我花了很多时间来理解为什么会这样,但是-在一张纸上放着我的笔记的帮助下-我应该能够证明这一点。
然后,我阅读了http://learnyouahaskell.com/for-a-few-monads-more#reader。我们再次以monadic语法重新介绍了这些内容:
do
a <- fa
b <- fb
c <- fc
d <- fd
return (f a b c d)
Run Code Online (Sandbox Code Playgroud)
尽管我需要另一张A4笔记来证明这一点,但我现在非常有信心,这也意味着相同:
f (fa x) (fb x) (fc x) (fd x)
Run Code Online (Sandbox Code Playgroud)
我糊涂了。为什么?这有什么用?
或者,更准确地说:在我看来,这只是复制了函数的功能作为应用程序,但语法更为冗长。
因此,您能否举一个例子,说明Reader monad能否像应用程序那样起作用?
其实,我也想问问有什么用任何这些二:应用性功能或阅读器单子-因为同时能够同样的论点适用于四种功能(fa,fb,fc,fd …
我有一些看起来像这样的代码,忽略了与我的问题无关的所有代码:
import qualified Control.Monad.Reader as Reader
data FooEnv = FooEnv { bar :: Int -> Int }
type FooReader = Reader.Reader FooEnv
foo :: Int -> FooReader String
foo i = Reader.liftM show $ bar' i
where
bar' i' = do
bar'' <- Reader.asks bar
return $ bar'' i'
Run Code Online (Sandbox Code Playgroud)
有没有办法重构这个?具体来说,嵌套bar'函数最让我困扰.这可以浓缩成一行吗?
reader-monad ×10
monads ×8
haskell ×6
scala ×3
scalaz ×2
applicative ×1
clojure ×1
do-notation ×1
kleisli ×1
purescript ×1
refactoring ×1
state-monad ×1