是否有可能從表達的秒差距chainl1
組合子不使用秒差距定義的單子實例?是否可以使用應用程序來表示chainl1?
chainl1 p op =
do x <- p
rest x
where
rest x = do f <- op
y <- p
rest (f x y)
<|> return x
是否有可能從表達的秒差距chainl1
組合子不使用秒差距定義的單子實例?是否可以使用應用程序來表示chainl1?
chainl1 p op =
do x <- p
rest x
where
rest x = do f <- op
y <- p
rest (f x y)
<|> return x
是的,這就是:
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)
由於對op
和p
進行解析,結果被立即應用,但由於p
是op
右操作數,它需要一個flip
。
所以,many (flip <$> op <*> p)
結果類型爲f [a -> a]
。然後通過foldl
從左到右應用該功能列表,初始值爲p
。
醜但等效Applicative
定義:
chainl1 p op =
p <**>
rest
where
rest = flip <$> op <*>
p <**>
pure (.) <*> rest
<|> pure id
相反左側參數x
明確的傳遞到右手側op
,這種應用形式「鏈」 op
的部分地施加到其右經由側參數(因此flip <$> op <*> p
)擡起組合子(.)
然後應用經由(<**>)
最左邊p
到所得rest :: Alternative f => f (a -> a)
。
當我嘗試這與'chainl1(讀<$>許多位)((+)<$符 '+' <|>(*)<$字符 '*')'的' 「1 + 2 * 3 + 4」'我得到17而不是13. –
它需要'flip(。)'而不是'(。)',那麼它就可以正常工作。 –
你願意解釋一下嗎?爲什麼摺疊和翻轉? – adamse