7381


`X(数字)`という形式の識別子をパースするパーサーを`parsers`ライブラリで書こうと思い、`Text.Parser.Token.Style.emptyIdents`を使って以下のような`IdentifierStyle`を定義しましたが、型エラーになってしまいます。

[code]

    import Text.Trifecta
    import Text.Parser.Token.Style
    
    identStyle :: IdentifierStyle Parser
    identStyle = emptyIdents {
      _styleStart = char 'X' :: Parser Char,
      _styleLetter = digit :: Parser Char
      }
    
    -- パーサをこのように定義したい(例: "X3" -> Var 3)
    ident = Var . (read . tail) <$> ident
    
[/code]

現状はとりあえずnaiveに`ident = Var . read <$> (char 'X' >> many
digit)`と定義していますが、何故上のコードで型エラーが出るのか知りたいです。

具体的な型エラーは以下のようになります。

[code]

    No instance for (Text.Parser.Token.TokenParsing t0)
      arising from a use of    Text.Parser.Token.Style.emptyIdents   
    The type variable    t0    is ambiguous
    Note: there are several potential instances:
      instance (Text.Parser.Token.TokenParsing m,
                Control.Monad.MonadPlus m) =>
               Text.Parser.Token.TokenParsing
                 (transformers-0.3.0.0:Control.Monad.Trans.Identity.IdentityT m)
        -- Defined in    Text.Parser.Token   
      instance parsec-3.1.8:Text.Parsec.Prim.Stream
                 s m ghc-prim:GHC.Types.Char =>
               Text.Parser.Token.TokenParsing
                 (parsec-3.1.8:Text.Parsec.Prim.ParsecT s u m)
        -- Defined in    Text.Parser.Token   
      instance attoparsec-0.12.1.3:Data.Attoparsec.Internal.Types.Chunk
                 t =>
               Text.Parser.Token.TokenParsing
                 (attoparsec-0.12.1.3:Data.Attoparsec.Internal.Types.Parser t)
        -- Defined in    Text.Parser.Token   
      ...plus 12 others
    In the expression: Text.Parser.Token.Style.emptyIdents
    In the expression:
      Text.Parser.Token.Style.emptyIdents
        {Text.Parser.Token._styleStart = Text.Parser.Char.char 'X' ::
                                           Text.Trifecta.Parser.Parser ghc-prim:GHC.Types.Char,
         Text.Parser.Token._styleLetter = Text.Parser.Char.digit ::
                                            Text.Trifecta.Parser.Parser ghc-prim:GHC.Types.Char}
    In an equation for    identStyle   :
        identStyle
          = Text.Parser.Token.Style.emptyIdents
              {Text.Parser.Token._styleStart = Text.Parser.Char.char 'X' ::
                                                 Text.Trifecta.Parser.Parser ghc-prim:GHC.Types.Char,
               Text.Parser.Token._styleLetter = Text.Parser.Char.digit ::
                                                  Text.Trifecta.Parser.Parser ghc-prim:GHC.Types.Char}
    
[/code]


CC BY-SA 3.0
2015-03-01T07:54:54.953
7270
2015-03-03T10:07:32.660
2781
question
haskell
Text.Parser.Token.StyleのemptyIdentsの使い方について


Haskellのレコード更新構文は、更新の前後で型が変わらないことを要求しません。このため、更新後の型が決まっていても更新前の型が完全には決まらないことがあります。この例では、`emptyIndents`の型が`TokenParsing
m => IdentifierStyle m`ですが、この`m`を決める手掛りがないため曖昧エラーが発生しています。

回避する方法はいくつかあります。

  * 明示的に型注釈を与える。
[code]     identStyle' :: IdentifierStyle Parser

    identStyle' = (emptyIdents :: IdentifierStyle Parser) {
      _styleStart = char 'X',
      _styleLetter = digit
      }
    
[/code]

  * 更新を二回に分けることで型の自由度をなくす。
[code]     identStyle'' :: IdentifierStyle Parser

    identStyle'' = emptyIdents {
      _styleStart = char 'X'
      } {
      _styleLetter = digit
      }
    
[/code]

  * 用意されているレンズを使う。
[code]     identStyle''' :: IdentifierStyle Parser

    identStyle''' = emptyIdents
      & styleStart .~ char 'X'
      & styleLetter .~ digit
    
[/code]


CC BY-SA 3.0
2015-03-03T10:07:32.660
7381
2015-03-03T10:07:32.660
8654
7270
answer