[英]How to combine two composed applicative functors?
我有兩個組合的應用函子Maybe [Integer]
並想將它們與<$>
/ <*>
結合,但我堅持應用應用操作。 以下內容不進行類型檢查:
(<*>) (<*>) ((<$>) ((+) <$>) $ Just [1,2,3]) $ Just [4,5,6]
預期結果:
Just [5,6,7,6,7,8,7,8,9]
仿函數部分起作用,即作為第一個參數傳遞給<*>
的中間值是Just [Integer -> Integer]
。 我習慣了 S 表達式,所以我很難使用 Haskell 語法。 我知道Compose
,但我只對沒有抽象的組合感興趣。
正如夏立耀所說,使用liftA2
可以減少混亂。
但是,如果您仍然想看看它在底層操作方面會變成什么,我們可以擴展liftA2
的定義:
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 f x y = f <$> x <*> y
所以解決方案變成
(liftA2 . liftA2) (+) (Just [1,2,3]) (Just [4,5,6])
= liftA2 (liftA2 (+)) (Just [1,2,3]) (Just [4,5,6])
= (\f x y -> f <$> x <*> y) ((\f x y -> f <$> x <*> y) (+)) (Just [1,2,3]) (Just [4,5,6])
= ((\f x y -> f <$> x <*> y) (+)) <$> Just [1,2,3] <*> Just [4,5,6]
= (\x y -> (+) <$> x <*> y) <$> Just [1,2,3] <*> Just [4,5,6]
現在,這不像上面的示例那樣采用無點樣式,我真的認為將其轉換為無點有幫助,但這是來自http://pointfree.ZF98ED07A4D5F50F7DEFZ1410D 的 output :
((<*>) . ((+) <$>)) <$> Just [1, 2, 3] <*> Just [4, 5, 6]
我們可以通過 eta-expanding 看到這是相同的:
(<*>) . ((+) <$>)
= \x y -> ((<*>) . ((+) <$>)) x y
= \x y -> ((<*>) $ ((+) <$>) x) y
= \x y -> ((<*>) ((+) <$> x)) y
= \x y -> (<*>) ((+) <$> x) y
= \x y -> ((+) <$> x) <*> y
= \x y -> (+) <$> x <*> y
liftA2
可能比(<*>)
更容易混淆。
(+) :: Int -> Int -> Int
liftA2 (+) :: [Int] -> [Int] -> [Int]
liftA2 (liftA2 (+)) :: Maybe [Int] -> Maybe [Int] -> Maybe [Int]
liftA2 (liftA2 (+)) (Just [1,2,3]) (Just [4,5,6])
兩個Applicative
的組合始終是一個Applicative
(與Monad
的情況不同)。
我們可以在這里使用newtype
的Compose
Data.Functor.Compose
來發揮我們的優勢:
newtype Compose f g a = Compose { getCompose :: f (g a) }
它需要一些包裝,但這種解決方案在適當的情況下可能很有用:
example :: Maybe [Int]
example =
getCompose ((+) <$> Compose (Just [1,2,3]) <*> Compose (Just [4,5,6]))
另一種方法是使用ListT
轉換器。 雖然在這種情況下它工作得很好,但由於某種原因,它是一個折舊的轉換器,用紅色標記為"Deprecated: This transformer is invalid on most monads" 。
import Control.Monad.Trans.List
doit :: (Int-> Int -> Int) -> Maybe [Int] -> Maybe [Int] -> Maybe [Int]
doit f mt1 mt2 = runListT $ f <$> (ListT mt1) <*> (ListT mt2)
λ> doit (+) (Just [1,2,3]) (Just [4,5,6])
Just [5,6,7,6,7,8,7,8,9]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.