2

私は自分でスキームを書くチュートリアルに取り組んでいます.1つのコードブロックを見て、バインドと代入の違いについて疑問に思いました:

 parseAtom = do first <- letter <|> symbol
            rest <- many (letter <|> digit <|> symbol)
            let atom = first:rest
            return $ case atom of 
                       "#t" -> Bool True
                       "#f" -> Bool False
                       _    -> Atom atom

なぜlet atom =代わりにatom <-?したがって、私は試しました:

parseAtom = do first <- letter <|> symbol
           rest <- many (letter <|> digit <|> symbol)
           atom <- first : rest
           return $ case atom of
                "#t" -> Bool True
                "#f" -> Bool False
                _ -> Atom atom

そして、コンパイルエラーが発生します:

    Couldn't match expected type `[Char]'
       against inferred type `Text.Parsec.Prim.ParsecT
                                String () Data.Functor.Identity.Identity Char'
In a stmt of a 'do' expression: atom <- first : rest

doこれが何を意味するのか正確にはわかりませんが、これはおそらくまたは モナドの不正確な理解によるものです。(私はHaskell の学習を他のさまざまなモナド/do チュートリアルと一緒に読んだことがあります。他の SO の質問では、インデントがここで問題を引き起こすことがよくあることに注意してください。ただし、正しくインデントしていると思います)

4

2 に答える 2

5

あなたはパーサーモナドの中にいるので、 の右側<-はパーサー式である必要があります。ただしfirst : rest、パーサー式ではなく、単なるリスト (具体的には文字列) です。

指定されたパーサーv <- someParserを入力に適用し、一致したテキストを に保存しますv。文字列はパーサーではなく、入力に適用できず、に格納する一致するテキストがありませんv。したがって、文字列を に格納するvだけで済みます。これは、 と記述して行いますlet v = someString

于 2013-06-09T16:43:20.193 に答える
5

do-notationと do-notation 内のletブロックの2 つの構文糖構造体を扱っています。正しい関数の実装を脱糖するだけで、物事が明らかになるはずです。

オリジナル

parseAtom = do 
  first <- letter <|> symbol
  rest <- many (letter <|> digit <|> symbol)
  let atom = first:rest
  return $ case atom of 
    "#t" -> Bool True
    "#f" -> Bool False
    _    -> Atom atom

Let-block 脱糖

parseAtom = do 
  first <- letter <|> symbol
  rest <- many (letter <|> digit <|> symbol)
  let 
    atom = first : rest
    in do
      return $ case atom of 
        "#t" -> Bool True
        "#f" -> Bool False
        _    -> Atom atom

完全脱糖

parseAtom =
  (letter <|> symbol) >>= \first ->
  many (letter <|> digit <|> symbol) >>= \rest ->
  let 
    atom = first : rest
    in return $ case atom of 
      "#t" -> Bool True
      "#f" -> Bool False
      _    -> Atom atom

また、 do 表記内の単純なlet 式は、予想どおりbind 式に置き換えることができることにも注意してください。に翻訳できます。returnlet atom = first:restatom <- return $ first : rest

于 2013-06-09T17:38:54.480 に答える