简体   繁体   中英

Are monads expressions, or are there statements in Haskell?

I have an ontological question about monads in haskell; I'm shaky on whether the language makes a distinction between statements and expressions at all. For example, I feel like in most other languages anything with a signature like a -> SomeMonadProbs () would be considered a statement. That said, since haskell is purely functional, and functions are composed of expressions, I'm a wee bit confused on what haskell would say about monads in terms of their expression-hood.

Monad is just one interface for interacting with expressions. For example, consider this list comprehension implemented using do notation:

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

That desugars to:

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

... and substituting in the definition of (>>=) for lists gives:

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

The important idea is that anything you can do using do notation can be replaced with calls to (>>=) .

The closest thing to "statements" in Haskell are syntactic lines of a do notation block, such as:

x <- [1..3]

These lines do not correspond to isolated expressions, but rather syntactic fragments of an expression which are not self-contained:

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

So it's really more appropriate to say that everything is an expression in Haskell, and do notation gives you something which appears like a bunch of statements but actually desugars to a bunch of expressions under the hood.

Here are few thoughts.

a >>= b is an application just like any other application, so from syntactic point of view there are clearly no statements in Haskell, only expressions.

From semantic point of view (see for example Tackling the awkward squad paper) there are "denotational" and "operational" fragments of Haskell semantics.

The denotational fragment treats >>= similar to a data constructor, so it considers a >>= b to be in WHNF. The "operational" fragment "deconstructs" the values in IO monad and performs different effects in the process.

When reasoning about programs, you often don't need to consider the "operational" fragment at all. For example, when you refactor foo a >> foo a into let bar = foo a in bar >> bar you don't care about the nature of foo , so IO actions are indistinguishable from any other values here.

It's where Haskell shines, and it's tempting to say there are no statements at all, however it leads to funny and somewhat paradoxical conclusion. For example, C preprocessor language can be considered a denotational fragment of C. So C has denotational and operational fragments too, but nobody says that C is purely functional or has no statements. See The C language is purely functional post for a detailed treatment of this matter.

Haskell of course differs from C quantitatively: its denotational fragment is expressive enough to be practically useful, so you have to think about underlying transitions in its operational semantics less often than in C.

But when you have to think about those transitions, like when reasoning about the order of data written to a network socket, you have to resort to that statement-after-statement thinking.

So while IO actions are not themselves statements and in a certain narrow technical sense there are no statements at all, the actions represent the statements so I think it's fair to say that statements are present in Haskell in a very indirect form.

whether the language makes a distinction between statements and expressions at all

It does not. There are no productions for "statement" or anything like that in the grammar, and nothing is called "statement" or anything equivalent (as far as I know) in the language description.

The language report calls elements inside the do notation "statements". There are two kinds of statements that are not expressions: pat <- exp`` and let decls`.

in most other languages anything with a signature like a -> SomeMonadProbs () would be considered a statement

Haskell is different from most other languages. That's kinda its point (not being different for the sake of it, obviously, but unifying expressions and statements into a single construct).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM