Haskell中不同类型的嵌套应用函子 [英] Nested applicative functors of different types in Haskell

查看:83
本文介绍了Haskell中不同类型的嵌套应用函子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想制作不同类型的嵌套应用函子.例如,嵌套的不同类型的简单函子(以ghci为单位)可以很好地工作:

I'd like to make the nested applicative functors of different types. For example, nested simple functors of different types (in ghci) work fine:

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

但是对于不同类型的应用函子:

But for applicative functors of different types:

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

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

不起作用!我想获得这样的东西:

isn't working! I want to obtain something like this:

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

我知道应用函子在函子和单子之间处于中间位置.我可以将本练习看作是有关monad变压器的主题之前的初步准备.

I know that applicative functors have intermediate position between functors and monads. And I can see this exercise as preliminary before topic about monad transformers.

推荐答案

在这种情况下,您需要:

In this case, you want:

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

或者:

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

外部… <$> … <*> …liftA2Maybe上运行,而内部… <$> … <*> …liftA2[]上运行.如果您不知道这些,可以向GHCi询问您应该放置在其中的类型,例如带有打孔的类型,来找出答案:

The outer … <$> … <*> … or liftA2 operates on Maybe, while the inner one operates on []. If you didn’t know this, you could figure it out by asking GHCi for the type of what you should put there, for example with a typed hole:

: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).

And the behaviour you want for combining the lists is \ xs ys -> (*) <$> xs <*> ys, which can be abbreviated liftA2 (*). ((*) <$>) or fmap (*) didn’t work because that’s only half of what you need: it operates on a single list (using Functor), while you want to combine two (using Applicative).

当然,liftA2 (liftA2 (*))适用于元素为数字的任何两个嵌套的应用函子:

Of course, liftA2 (liftA2 (*)) works on any two nested applicative functors whose elements are numeric:

(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]

甚至更奇特的东西,例如函数列表:

Or even something more exotic, like lists of functions:

($ (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]

这篇关于Haskell中不同类型的嵌套应用函子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆