簡體   English   中英

Haskell中不同類型的嵌套應用函子

[英]Nested applicative functors of different types in Haskell

我想制作不同類型的嵌套applicative functor。 例如,不同類型的嵌套簡單仿函數(在ghci中)可以正常工作:

Prelude> ((+2) <$>) <$> (Just [1..4])
Just [3,4,5,6]

但對於不同類型的應用函子:

Prelude> ((*) <$>)  <$> (Just [1,2,3]) <*> (Just [4,5,6,7])

<interactive>:56:1: error:
    * Couldn't match type `[Integer -> Integer]' with `[Integer] -> b'

不工作! 我想獲得這樣的東西:

Just [4,5,6,7,8,10,12,14,12,15,18,21]

我知道應用仿函數在仿函數和monad之間具有中間位置。 在關於monad變形金剛的主題之前,我可以看到這個練習是初步的。

除了嵌套升降機和fmaps之外,構建應用程序Data.Functor.Compose函數的另一個選項是Data.Functor.Compose

newtype Compose f g a = Compose { getCompose :: f (g a) }

例如:

ghci> let Compose result = (*) <$> Compose (Just [1,2,3]) <*> Compose (Just [4,5,6,7])
ghci> result
Just [4,5,6,7,8,10,12,14,12,15,18,21]

Applicative如此良好,以至於單個newtype足以組成作為實例的任何兩種類型。 除了嵌套之外,還有其他方法可以將它們組合在一起,例如ProductDay卷積:

data Product f g a = Pair (f a) (g a)

data Day f g a = forall b c. Day (f b) (g c) (b -> c -> a)

Monad雖然沒有構圖,所以我們需要為每個monad添加一個不同的新類型 ,以便用第一個monad的能力來增強其他monad。 我們稱之為newtypes monad變換器。

在這種情況下,您需要:

liftA2 (*) <$> Just [1, 2, 3] <*> Just [4, 5, 6, 7]

要么:

liftA2 (liftA2 (*)) (Just [1, 2, 3]) (Just [4, 5, 6, 7])

外部… <$> … <*> …liftA2Maybe ,而內部操作在[] 如果您不知道這一點,您可以通過向GHCi詢問您應該放在那里的類型來解決這個問題,例如使用打字孔:

:t _ <$> (Just [1 :: Int, 2, 3]) <*> (Just [4 :: Int, 5, 6, 7]) :: Maybe [Int]

它回饋:

_ :: [Int] -> [Int] -> [Int]

組合列表所需的行為是\\ xs ys -> (*) <$> xs <*> ys ,可以縮寫為liftA2 (*) ((*) <$>)fmap (*)不起作用,因為它只是你需要的一半:它在單個列表上運行(使用Functor ),而你想要組合兩個(使用Applicative )。

當然, liftA2 (liftA2 (*))適用於任何兩個嵌套的applicative functor,它們的元素是數字的:

(Applicative f, Applicative g, Num a)
  => f (g a) -> f (g a) -> f (g a)

例如,嵌套列表:

liftA2 (liftA2 (*)) [[1], [2], [3]] [[4, 5, 6]]
== [[4,5,6],[8,10,12],[12,15,18]]

-- (Transposing the inputs transposes the output.)
liftA2 (liftA2 (*)) [[1, 2, 3]] [[4], [5], [6]]
== [[4,8,12],[5,10,15],[6,12,18]]

或列出的Maybe

liftA2 (liftA2 (*)) [Just 1, Nothing, Just 3] [Just 4, Nothing, Just 6]
== [Just 4, Nothing, Just 6,
    Nothing, Nothing, Nothing,
    Just 12, Nothing, Just 18]

甚至更奇特的東西,比如功能列表:

($ (3, 5)) <$> (liftA2 (+) <$> [fst, snd] <*> [snd, fst])
== [fst (3, 5) + snd (3, 5),
    fst (3, 5) + fst (3, 5),
    snd (3, 5) + snd (3, 5),
    snd (3, 5) + fst (3, 5)]
== [3+5, 3+3, 5+5, 5+3]
== [8,6,10,8]

我們也可以通過前奏函數來完成這一過程。 你的第一部分很好。

((*) <$>) <$> (Just [1,2,3])類型為Num a => Maybe [a -> a]

我們所需要的只是將Maybe monad中的應用列表映射到Maybe monad中的列表。 所以一種方法可能是將第一部分綁定到(<$> Just [4, 5, 6, 7]) . (<*>) :: Num a => [a -> b] -> Maybe [b] (<$> Just [4, 5, 6, 7]) . (<*>) :: Num a => [a -> b] -> Maybe [b]

((*) <$>)  <$> (Just [1,2,3]) >>= (<$> Just [4,5,6,7]) . (<*>)

屈服於

Just [(1*),(2*),(3*)] >>= (<$> Just [4,5,6,7]) . (<*>)

屈服於

([(1*),(2*),(3*)] <*>) <$> Just [4,5,6,7]

屈服於

Just [4,5,6,7,8,10,12,14,12,15,18,21] 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM