eps*_*lbe 10 language-agnostic monads functional-programming
前几天我在讨论函数式编程 - 特别是Haskell和一些Java/Scala人,他们问我Monads是什么,他们在哪里需要.
以及定义和例子并不是那么难- ,,Maybe Monad 等等,让每个人都至少部分,确定跟我说单子是一件好事.IO MonadState Monad
但Monad需要在哪里 - Maybe可以通过魔法值来避免,例如-1在设置Integer或""设置中String.我写了一个没有StateMonad 的游戏,这个游戏并不好,但是初学者就是这么做的.
所以我的问题是:Monads在哪里必要? - 根本无法避免.(并没有混淆 - 我喜欢Monads并使用它们,我只是想知道).
我想我必须澄清一点,我不认为使用"Magic Values"是一个很好的解决方案,但很多程序员都会使用它们,特别是在C语言或SHell的低级语言中,通常会返回错误-1.
我已经清楚,不使用monad不是一个好主意.抽象通常非常有用,但也很复杂,因此许多人都在努力解决monad的概念.
我的问题的核心是,如果有可能做到,例如IO,没有monad,仍然是纯粹和功能.我知道将一个已知的良好解决方案放在一边,以及用燧石和火种点燃火灾而不是使用打火机将是乏味和痛苦的.
文章@Antal SZ指的是很棒你可以发明monad,我浏览它,当我有更多时间时肯定会读它.更有启发性的答案隐藏在@Antal SZ提到的博客文章的评论中我记得monad之前的时间,这是我在问这个问题时所寻找的东西.
Ant*_*sky 12
我认为你不需要 monad.当你使用某些功能时,它们只是一种自然显现的模式.我见过这种观点的最佳解释是Dan Piponi(sigfpe)的优秀博客文章"你可能已经发明了Monads!(也许你已经拥有.)",这个答案的灵感来自于.
你说你没有使用州monad就写了一个游戏.它看起来像什么?你很有可能最终使用类似的类型的函数openChest :: Player -> Location -> (Item,Player)(打开一个箱子,可能会损坏玩家的陷阱,并返回找到的项目).一旦你需要组合它们,你可以手动(let (item,player') = openChest player loc ; (x,player'') = func2 player' y in ...)或重新实现状态monad的>>=运算符.
或者假设我们使用哈希映射/关联数组的语言,我们不使用monad.我们需要查找一些项目并与之合作; 也许我们正试图在两个用户之间发送消息.
send username1 username2 = {
user1 = users[username1]
user2 = users[username2]
sendMessage user1 user2 messageBody
}
Run Code Online (Sandbox Code Playgroud)
但是等等,这不起作用; username1并且username2可能会丢失,在这种情况下,它们将是nil或者-1不是所需的值.或者在关联数组中查找键会返回type的值Maybe a,因此这甚至会是类型错误.相反,我们必须写出像
send username1 username2 = {
user1 = users[username1]
if (user1 == nil) return
user2 = users[username2]
if (user2 == nil) return
sendMessage user1 user2 messageBody
}
Run Code Online (Sandbox Code Playgroud)
或者,使用Maybe,
send username1 username2 =
case users[username1] of
Just user1 -> case users[username2] of
Just user2 -> Just $ sendMessage user1 user2 messageBody
Nothing -> Nothing
Nothing -> Nothing
Run Code Online (Sandbox Code Playgroud)
伊克!这是混乱和过度嵌套.因此,我们定义了某种功能,它结合了可能失败的动作.也许是这样的
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
f >>= Just x = f x
f >>= Nothing = Nothing
Run Code Online (Sandbox Code Playgroud)
所以你可以写
send username1 username2 =
users[username1] >>= $ \user1 ->
users[username2] >>= $ \user2 ->
Just (sendMessage user1 user2 messageBody)
Run Code Online (Sandbox Code Playgroud)
如果你真的不想使用Maybe,那么你可以实现
f >>= x = if x == nil then nil else f x
Run Code Online (Sandbox Code Playgroud)
同样的原则适用.
但实际上,我建议阅读"你可以发明Monad!" 这是我对monad有这种直觉的地方,并且更好地和更详细地解释了它.Monad在使用某些类型时会自然出现.有时候你会明确地表达这种结构,有时你却不这样做,但仅仅因为你没有采取这种结构并不意味着它不存在.在您不需要使用特定结构的意义上,您永远不需要使用monad ,但通常这是很自然的事情.并且识别共同模式,就像在许多其他事情中一样,可以允许您编写一些非常通用的代码.
(另外,正如我用过的第二个例子所示,请注意你已经用洗澡水将婴儿扔掉了,取而代之的Maybe是魔法值.仅仅因为Maybe是monad并不意味着你必须像一个人一样使用它;列表也是monad ,功能(形式r ->),但你不建议摆脱它们!:-))