2011-10-10 5 views

答えて

5

はい、それは次のとおりです。

chainl1 p op = foldl (flip ($)) <$> p <*> many (flip <$> op <*> p) 

アイデアは、あなたがp (op p)*を解析し、(...(((p) op p) op p)...)としてそれを評価しなければならないということです。

それは定義を少し拡大に役立つかもしれない:

chainl1 p op = foldl (\x f -> f x) <$> p <*> many ((\f y -> flip f y) <$> op <*> p) 

oppのペアが解析されるように、結果がすぐに適用されますが、popの右オペランドであるので、それはA必要flip

したがって、many (flip <$> op <*> p)の結果タイプはf [a -> a]です。この関数リストは、pという初期値で、左から右に、foldlで適用されます。 Applicative

+0

もう少し説明してください。なぜfoldlとフリップ? – adamse

0

醜い同等の定義:

chainl1 p op = 
    p <**> 
    rest 
    where 
    rest = flip <$> op <*> 
      p <**> 
      pure (.) <*> rest 
     <|> pure id 

の代わりに明示的に右側opに左側の引数xの通過、このApplicativeのフォーム「チェーン」op年代には、部分的に彼らの右に適用されます(したがってflip <$> op <*> p)を持ち上げコンビネータ(.)を介して受信し、rest :: Alternative f => f (a -> a)に最も左のp(<**>)で適用します。

+0

私はこれを '' 1 + 2 * 3 + 4 "'の上に 'chainl1(<$>を読んでください)((+)<$ char '+' <|>(*)<$ char '*')' 17の代わりに17を返します。 –

+0

'(。)'の代わりに 'flip(。)'が必要です。 –