简体   繁体   English

Haskell Monads中的`let .. in do`和`<-`表示法有什么区别?

[英]What is the difference between `let .. in do` and `<-` notation in Haskell Monads?

I'm trying to implement a function which converts a string to a list of Maybe Ints, eg readInts "1 2 42 foo" = [Just 1,Just 2,Just 42,Nothing] . 我正在尝试实现一个将字符串转换为Maybe Ints列表的函数,例如readInts "1 2 42 foo" = [Just 1,Just 2,Just 42,Nothing]

My first aproach was: 我的第一个方法是:

readInts (s::String) = do {
    ws <- words s;
    return (map (readMaybe::(String -> Maybe Int)) ws)
}

This resulted in the following error: 这导致以下错误:

lab_monad.hs:20:52:
    Couldn't match type ‘Char’ with ‘[Char]’
    Expected type: [String]
      Actual type: String
    In the second argument of ‘map’, namely ‘ws’
    In the first argument of ‘return’, namely
      ‘(map (readMaybe :: String -> Maybe Int) ws)’
Failed, modules loaded: none.

What I tried next (and worked), was: 我接下来尝试(并工作)的是:

readInts (s::String) = do {
    let ws = (words s) in do
        return (map (readMaybe::(String -> Maybe Int)) ws)
} 

My question here is, words s obviously is of type [String] . 我的问题是, words s显然是[String]类型。 Why does the interpreter say it is a String ? 为什么解释器说它是String What am I not understanding about <- operator? 我对<-运算符不了解什么?

ws <- words s , in the list monad, nondeterministically assigns one word from words s to ws ; ws <- words s ,在单子列表中,不确定地将words s 一个单词分配给ws the remaining code simply works with that one word, and the return function "magically" combines the results of working on all the words into the result list. 剩下的代码仅使用该单词, return函数“神奇地”将所有单词的运算结果组合到结果列表中。

readInts s = do
   ws <- words s  -- ws represents *each* word in words s
   return (readMaybe ws)

The do notation is just syntactic sugar for using monadic bind : do表示法只是使用monadic bind语法糖:

readInts s = words s >>= (\ws -> return (readMaybe ws))

Without using the Monad instance for lists, you can use map to apply the same function to each word. 在不使用Monad实例进行列表的情况下,可以使用map将相同的功能应用于每个单词。

readInts s = map readMaybe (words s)

let , on the other hand, simply provides a name for a more complicated expression to be used in another expression. 另一方面, let仅提供用于另一个表达式的更复杂表达式的名称。 It can be considered syntactic sugar for defining and immediately applying an anonymous function. 可以将其视为用于定义和立即应用匿名函数的语法糖。 That is, 那是,

let x = y + z in f x

is equivalent to 相当于

(\x -> f x) (y + z)
  ^     ^      ^
  |     |      |
  |     |      RHS of let binding
  |     part after "in"
  LHS of let binding

A let statement with multiple bindings is equivalent to nested let statements: 一个let与多个绑定语句相当于嵌套let语句:

let x = y + z
    a = b + c
in x + a

is equivalent to 相当于

let x = y + z
in let a = b + c
   in x + a

which desugars to 哪个讨价还价

(\x -> (\a -> x + a)(b + c))(y + z)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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