在不同的问题上,我发现了关于使用(->)Monads实例的评论中的提示,例如用于实现无点样式.
至于我,这有点过于抽象.好吧,我已经看到了Arrow实例,在(->)我看来,它(->)可以在实例表示法中使用,但不能在类型声明中使用(这可能只是另一个问题的东西).
有没有任何例子使用(->)Monad的例子?还是一个很好的链接?
很抱歉,如果这个问题可能已经在这里讨论过,但是搜索" (->)Monad实例"会给你很多次点击,因为你可以想象......因为几乎所有关于Haskell的问题都涉及到(->)"Monad".
我知道monad是什么以及如何使用它们.我不明白的是,是什么让Option一个单子?
在Haskell中,monad Maybe是一个monad,因为它是从Monad类中实例化的(它具有至少2个必要的函数return,bind并且实现了类Monad,实际上是monad).
但是在Scala我们有这个:
sealed abstract class Option[+A] extends Product with Serializable { ... }
trait Product extends Any with Equals { ... }
Run Code Online (Sandbox Code Playgroud)
没有任何与monad相关的东西.
如果我在Scala中创建自己的类,默认情况下它是monad吗?为什么不?
编辑2015这个问题及其答案已不再适用.它在C#6出现之前被问到,它具有空传播的opertor(?.),它避免了在这个问题和随后的答案中讨论的hacky-workarounds.截至2015年,在C#中,您现在应该使用Form.ActiveForm?.ActiveControl?.Name.
我一直在考虑.NET中的空传播问题,这常常导致丑陋的重复代码,如下所示:
尝试#1常用代码:
string activeControlName = null;
var activeForm = Form.ActiveForm;
if (activeForm != null)
{
var activeControl = activeForm.ActiveControl;
if(activeControl != null)
{
activeControlname = activeControl.Name;
}
}
Run Code Online (Sandbox Code Playgroud)
StackOverflow上有一些关于Maybe <T> monad的讨论,或者使用某种"if not null"扩展方法:
尝试#2,扩展方法:
// Usage:
var activeControlName = Form.ActiveForm
.IfNotNull(form => form.ActiveControl)
.IfNotNull(control => control.Name);
// Definition:
public static TReturn IfNotNull<TReturn, T>(T instance, Func<T, TReturn> getter)
where T : class
{
if (instance != null ) return getter(instance);
return null;
}
Run Code Online (Sandbox Code Playgroud)
我认为这更好,然而,重复的"IfNotNull"和lambdas会有一些语法混乱.我现在正在考虑这个设计:
尝试使用扩展方法#3,可能<T>
// Usage:
var activeControlName …Run Code Online (Sandbox Code Playgroud) 我在Haskell中编写了一堆代码来创建文本索引.top函数如下所示:
index :: String -> [(String, [Integer])]
index a = [...]
Run Code Online (Sandbox Code Playgroud)
现在我想给这个函数一个从文件读取的字符串:
index readFile "input.txt"
Run Code Online (Sandbox Code Playgroud)
哪个不起作用,因为readFile的类型为FilePath - > IO String.
无法将预期类型'String'与推断类型'IO String'匹配
我看到错误,但我找不到任何类型的函数:
IO String -> String
Run Code Online (Sandbox Code Playgroud)
我想成功的关键在于Monads的某些地方,但我找不到解决问题的方法.
在功能编程方面触及Monads之后,该功能是否实际上使语言变得纯粹,或者它是否只是另一个"从监狱免费卡中获取"来推理现实世界中的计算机系统,在黑板数学之外?
编辑:
这不是有人在这篇文章中所说过的火焰诱饵,而是一个真正的问题,我希望有人可以用枪击我说,证明,这是纯粹的.
此外,我正在研究关于其他不那么纯粹的功能语言和一些使用良好设计和比较纯度的OO语言的问题.到目前为止,在我非常有限的FP世界中,我仍然没有理解Monads的纯度,你会很高兴地知道我喜欢不变性的想法,这在纯度赌注中更为重要.
monads haskell functional-programming referential-transparency
大多数教程似乎提供了很多monad(IO,状态,列表等)的例子,然后期望读者能够抽象出整体原则,然后他们提到类别理论.通过尝试从例子中进行概括,我不会学得很好,我想从理论的角度理解为什么这种模式如此重要.
从这个线索来看: 任何人都可以解释Monads吗? 这是一个常见的问题,我已经尝试查看大多数建议的教程(除了我的linux机器上不能播放的Brian Beck视频):
有没有人知道从类别理论开始的教程,并用这些术语解释IO,状态,列表monad?以下是我未能成功的尝试:
据我所知,monad包含一个三元组:一个endo-functor和两个自然变换.
仿函数通常显示类型:(a - > b) - >(ma - > mb)我包括第二个括号只是为了强调对称性.
但是,这是一个endofunctor,所以域和codomain不应该像这样吗?:
(a - > b) - >(a - > b)
我认为答案是域和codomain都有一种类型:
(a - > b)| (ma - > mb)| (mma - > mmb)等......
但我不确定这是否有效或符合给定的仿函数的定义?
当我们继续进行自然变革时,它会变得更糟.如果我理解正确,自然变换是二阶函子(具有某些规则),它是从一个仿函数到另一个仿函数的仿函数.因为我们已经定义了上面的仿函数,一般类型的自然变换将是:((a - > b) - >(ma - > mb)) - >((a - > b) - >(ma - > mb ))
但是我们使用的实际自然变换有类型:
a - > ma
ma - >(a - > mb) - > mb
这些一般形式的子集是否在上面?为什么它们会自然变换?
马丁
像我之前的许多愚蠢的先驱一样,我正在努力穿越理解Monads的无轨荒地.
我仍然蹒跚而行,但我不禁注意到Python的with声明具有某种类似monad的质量.考虑这个片段:
with open(input_filename, 'r') as f:
for line in f:
process(line)
Run Code Online (Sandbox Code Playgroud)
将open()调用视为"单元",将块本身视为"绑定".实际的monad没有暴露(呃,除非f是monad),但模式就在那里.不是吗?或者我只是误将所有FP误认为是monadry?或者它只是凌晨3点,似乎有什么可信的?
一个相关的问题:如果我们有monad,我们是否需要例外?
在上面的片段中,I/O中的任何故障都可以从代码中隐藏.磁盘损坏,缺少指定文件和空文件都可以被视为相同.因此不需要可见的IO异常.
当然,Scala的Option类型类已经消除了可怕的Null Pointer Exception.如果你重新考虑作为Monads的数字(有NaN和DivideByZero作为特殊情况)......
就像我说的,早上3点.
C#语言设计一直(历史上)一直致力于解决特定问题,而不是寻找解决潜在的一般问题:例如参见http://blogs.msdn.com/b/ericlippert/archive/2009/07/09/ "IEnumerable vs. coroutines"的iterator-blocks-part-one.aspx:
我们本来可以做得更普遍.我们的迭代器块可以看作是一种弱的协程.我们本可以选择实现完整的协同程序,并且只是使迭代器块成为协程的特例.当然,协同程序反过来不如一流的延续; 我们可以实现continuation,在continuation方面实现协程,并在协程方面实现迭代器.
或者http://blogs.msdn.com/b/wesdyer/archive/2008/01/11/the-marvels-of-monads.aspx for SelectMany作为(某种)Monads的代理人:
C#类型系统的功能不足以为monad创建通用抽象,这是创建扩展方法和"查询模式"的主要动力.
我不想问为什么会这样(已经给出了许多好的答案,特别是在Eric的博客中,这可能适用于所有这些设计决策:从性能到复杂性的增加,无论是编译器还是程序员).
我想要了解的是async/await关键字所涉及的"一般构造"(我最好的猜测是延续monad - 毕竟,F#async是使用工作流实现的,据我所知是一个延续monad),以及它们如何与它相关(它们如何不同?,缺少什么?,为什么存在差距,如果有的话?)
我正在寻找类似于我链接的Eric Lippert文章的答案,但与async/await相关而不是IEnumerable/yield.
编辑:除了很棒的答案,一些有用的链接到相关的问题和建议的博客文章,我正在编辑我的问题列出他们:
我已经阅读了这篇文章,但最后一节并未理解.
作者说Monad给了我们上下文敏感性,但是只使用Applicative实例就可以实现相同的结果:
let maybeAge = (\futureYear birthYear -> if futureYear < birthYear
then yearDiff birthYear futureYear
else yearDiff futureYear birthYear) <$> (readMay futureYearString) <*> (readMay birthYearString)
Run Code Online (Sandbox Code Playgroud)
没有do语法肯定会更加丑陋,但除此之外我不明白为什么我们需要Monad.任何人都可以为我清除这个吗?
我正在努力了解这背后的动机MonadPlus.如果已经有类型Monad和Monoid?为什么有必要?
当然,实例Monoid是具体类型,而实例Monad需要单个类型参数.(有关有用的解释,请参阅Monoid与MonadPlus.)但是你不能重写任何类型约束
(MonadPlus m) => ...
Run Code Online (Sandbox Code Playgroud)
作为Monad和Monoid?的组合?
(Monad m, Monoid (m a)) => ...
Run Code Online (Sandbox Code Playgroud)
例如,guard从中获取功能Control.Monad.它的实施是:
guard :: (MonadPlus m) => Bool -> m ()
guard True = return ()
guard False = mzero
Run Code Online (Sandbox Code Playgroud)
我只能使用Monad和实现它Monoid:
guard' :: (Monad m, Monoid (m ())) => Bool -> m ()
guard' True = return ()
guard' False = mempty
Run Code Online (Sandbox Code Playgroud)
有人可以澄清 …