1

文字列を Maybe Ints のリストに変換する関数を実装しようとしていますreadInts "1 2 42 foo" = [Just 1,Just 2,Just 42,Nothing]

私の最初のアプローチは:

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

これにより、次のエラーが発生しました。

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.

次に試した(そして機能した)のは次のとおりです。

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

ここでの私の質問は、words s明らかに type[String]です。なぜ通訳者はそれが であると言うのStringですか? <-オペレーターについて何が理解できませんか?

4

1 に答える 1

5

ws <- words s、リスト モナドでは、非決定論的に1 つの単語を fromwords sに割り当てwsます。残りのコードはその 1 つの単語だけを処理し、関数はすべての単語を処理したreturn結果を "魔法のように" 結果リストに結合します。

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

表記法は、doモナディックを使用するための単なる構文糖衣ですbind

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

Monadリストのインスタンスを使用せずmapに、同じ関数を各単語に適用するために使用できます。

readInts s = map readMaybe (words s)

let一方、 は、別の式で使用されるより複雑な式の名前を提供するだけです。これは、無名関数を定義してすぐに適用するための構文糖衣と見なすことができます。あれは、

let x = y + z in f x

と同等です

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

複数のバインディングを持つステートメントは、ネストされたステートメントletと同等です。let

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

と同等です

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

脱糖するもの

(\x -> (\a -> x + a)(b + c))(y + z)
于 2018-03-18T17:42:55.340 に答える