是monads表达式,还是Haskell中有语句?

时间:2013-09-27 13:36:24

标签: haskell monads

我有一个关于哈斯克尔单子的本体论问题;我对这种语言是否区分语句和表达方式感到不满。例如,我觉得在大多数其他语言中,任何带有a -> SomeMonadProbs ()等签名的内容都会被视为一种陈述。也就是说,因为haskell是纯粹的功能,而且函数是由表达式组成的,所以我对于haskell在表达式方面对monad所说的内容感到有点困惑。

3 个答案:

答案 0 :(得分:9)

Monad只是一个用于与表达式交互的接口。例如,请考虑使用do表示法实现此列表理解:

example :: [(Int, Int)]
example = do
    x <- [1..3]
    y <- [4..6]
    return (x, y)

该desugars:

[1..3] >>= \x ->
[4..6] >>= \y ->
return (x, y)

...并在(>>=)的定义中替换列表给出:

concatMap (\x -> concatMap (\y -> [(x, y)]) [4..6]) [1..3]

重要的一点是,使用do表示法可以执行的操作可以替换为对(>>=)的调用。

Haskell中与“语句”最接近的是do符号块的句法行,例如:

x <- [1..3]

这些行不对应于孤立的表达式,而是表达式的语法片段,它们不是独立的:

[1..3] >>= \x -> ... {incomplete lambda}

所以说Haskell中的所有内容都是一个表达式更合适,do符号为你提供了一些看起来像一堆语句的东西,但实际上是对一堆表达式的贬低。

答案 1 :(得分:6)

这里有一些想法。

a >>= b就像任何其他应用程序一样是一个应用程序,所以从语法的角度来看,Haskell中只有表达式中没有语句。

从语义的角度来看(例如参见Tackling the awkward squad论文),有Haskell语义的“指称”和“可操作”片段。

指称片段将>>=视为与数据构造函数类似,因此它认为a >>= b位于WHNF中。 “操作”片段“解构”IO monad中的值,并在此过程中执行不同的效果。

在推理程序时,通常根本不需要考虑“可操作”片段。例如,当您将foo a >> foo a重构为let bar = foo a in bar >> bar时,您并不关心foo的性质,因此IO操作与此处的任何其他值无法区分。

这是Haskell闪耀的地方,并且很容易说没有任何陈述,但它会导致有趣且有些矛盾的结论。例如,C预处理器语言可以被认为是C的指称片段。所以C也有指称和操作片段,但是没有人说C是纯函数或没有语句。有关此问题的详细处理,请参阅The C language is purely functional帖子。

Haskell当然与C的定量不同:它的指称片段具有足够的表现力,实际上非常有用,所以你必须考虑其操作语义中的底层转换,而不是在C中。

但是当你必须考虑这些转换时,比如在推理写入网络套接字的数据顺序时,你必须采用语句后语句思维。

因此虽然IO操作本身不是语句,并且在某种狭隘的技术意义上根本没有语句,但代表语句,所以我认为可以说Haskell中存在语句以非常间接的形式。

答案 2 :(得分:5)

  

语言是否在语句和表达式之间进行区分

没有。在语法中没有“语句”或类似内容的产生,在语言描述中没有任何东西被称为“语句”或任何等价物(据我所知)。

语言报告调用do符号“语句中的元素”。有两种语句不是表达式:pat <- exp`` and let decls`。

  

在大多数其他语言中,任何带有a -> SomeMonadProbs ()签名的内容都将被视为声明

Haskell与大多数其他语言不同。这有点重要(显然不是为了它,而是将表达式和语句统一到一个构造中)。

相关问题