2017-01-15 10 views
2

はここのコードです:現在のコード、runParser (some item) "abcd"ループを有するなぜこれは 'データ'でループしますが 'newtype'でループしませんか?

import Control.Applicative 

-- newtype Parser a = Parser { runParser :: String -> [(a, String)] } 
data Parser a = Parser { runParser :: String -> [(a, String)] } 

instance Functor Parser where 
    fmap f (Parser p) = Parser (\s -> [(f x, s') | (x, s') <- p s ]) 

instance Applicative Parser where 
    pure a = Parser (\s -> [(a, s)]) 
    Parser q <*> Parser p = Parser (\s -> [(f x, s'') | (f, s') <- q s, (x, s'') <- p s']) 

instance Alternative Parser where 
    empty = Parser (\s -> []) 
    Parser q <|> Parser p = Parser (\s -> q s ++ p s) 

item = Parser (\s -> case s of 
        (x:xs) -> [(x, xs)] 
        _ -> [] 
      ) 

が、パーサはnewtypeとして宣言されている場合、それだけで正常に動作します。

+1

正確には何あなたは尋ねる?このことを示す例がありますか? – Alec

+0

この質問にはほとんど情報がありません。もっと詳細を共有しないと、何が起こっているのか分かりません。 [MCVE](http://stackoverflow.com/help/mcve)を提供する必要があります。 – chi

答えて

6

これはthe difference between data and newtypeのいずれかになるのに最適な方法です。ここでの問題の中心は、実際にはのパターンマッチングにあります。

instance Alternative Parser where 
    empty = Parser (\s -> []) 
    Parser q <|> Parser p = Parser (\s -> q s ++ p s) 

実行時に、newtypeはそれがラップしているタイプと同じものになっていることを覚えておいてください。そして、newtypeがパターンマッチした場合、GHCは何もしません.WNHFに評価するコンストラクタはありません。

逆に、dataが一致すると、パターンParser qはGHCにそのパーサーをWNHFに評価する必要があることを示します。これは問題です。someは無限の倍数の<|>です。

  • <|>Parserパターンを持っていない:そこdataの問題を解決するには2つの方法がある

    instance Alternative Parser where 
        empty = Parser (\s -> []) 
        q <|> p = Parser (\s -> runParser q s ++ runParser p s) 
    
  • 使用lazy patterns

    instance Alternative Parser where 
        empty = Parser (\s -> []) 
        ~(Parser q) <|> ~(Parser p) = Parser (\s -> q s ++ p s) 
    
+1

'<|>'が左に偏っているため、最初の厳密なパターンは問題ありません。したがって、これは 'Parser q <|>〜(Parser p)= ...'と書くことができます。もちろん、この場合の最良の解決法は 'newtype'を使うことです! – dfeuer

+0

ありがとう、それは多くの助けになります。私はまだWNHFに評価されている 'データ'と '<|>'の問題の関係を理解し​​ていません。 – Procrade

関連する問題