2013-10-25 38 views
6

我期待学习F#,但有一点让我感到困惑的是计算表达式(do-notation ??)语法和desugaring。Haskell程序员的计算表达式

在haskell中,您有一个非常简单的Monad类型类和用于将绑定和返回的desugaring注释的规则。添加关键字没有任何魔力;唯一必须匹配的是类型。

在F#中有一堆构建器,关键字和复杂性。

对于如何将一个概念映射到另一个概念有很好的解释吗?

我基本上想知道我是如何映射

do 
    x <- monadicComputation 
    foo x 
    someOtherMonadicComputation 
    let y = somePureComputation x 
    return $ bar y 

到F#。

haskell中唯一的关键字是do,(< - )和let。

回答

13

您不能在F#中编写通用单代码,而必须通过命名与该表达式相关联的构建器来指定您正在使用的monad。您的示例代码如下所示:

let example = async { 
    let! a = someAsyncComputation 
    foo a 
    do! someOtherAsyncComputation 
    let y = somePureComputation a 
    return (bar y) 
} 

async计算表达式类型。在绑定monadic值时使用'bang'模式(do !, let!等),而常规关键字用于非单值数值。

let!对应于结合(>>=)let对应于letdo符号。 return对应于return,而return!用于产生现有的一元值。 do!类似于(>>),它为其效果执行单值,而do用于非单点效果,在Haskell中没有并行效果。

+1

我想你的意思是说'do!'与'(>>)'相似。 – MisterMetaphor

+0

@MisterMetaphor - 是的,谢谢。 – Lee

+0

我希望我能接受所有这些答案,但我会采取这一个,因为看起来社区已经把它投得最多 – nimish

3

哈斯克尔做记号具有映射到bind功能只有一个特殊的语法,即<-,一切里面做的只是正常的功能应用,其结果是单子类型,例如:returnputStr

同样在F#中,您有let!来表示bind操作和return关键字语法糖(不像haskell中的正常函数调用,但此关键字映射到您定义的Return函数)。现在还有许多其他关键字您的计算表达式可以支持(如果不需要,可以轻松地忽略它们),它们全部记录在here中。这些额外的操作可以为您提供语法糖,以使用F#关键字而不是返回monadic值的正常函数。您可以看到,在F#计算表达式中可以重载的所有关键字都具有单值返回值。

所以基本上,您不必担心所有这些关键字,只要将它们视为正常的monad返回函数(具有可在文档中找到的特定类型签名),您可以使用F#关键字计算表达式语法。

4

如果您来自Haskell背景,那么您最近可能会对我编写的有关F#计算表达式的an academic article感兴趣。

它将计算表达式语法(这非常灵活)链接到Haskell中使用的标准类型类。如前所述,F#不容易让你编写代码通用于monad(它可以完成,但它不是惯用的),但另一方面它可以让你选择最合适的语法,你甚至可以得到很好的语法对于MonadPlus或单子变压器。

除此之外,通过利中提到async单子,这里是MonadPlus一个例子(使用序列表达 - 列表单子 - 作为例子):

let duplicate list = seq { 
    for n in list do 
    yield n 
    yield n ∗ 10 } 

或者用于解析器的计算表达式:

let rec zeroOrMore p = parse { 
    return! oneOrMore p 
    return [] } 
+1

我发现这个答案太晚了,现在链接似乎被破坏了。您能否通过正确的链接更新您的答案? – Nicolocodev