Function Haskell-将函数元组应用于值元组?

Function Haskell-将函数元组应用于值元组?,function,haskell,tuples,apply,pointfree,Function,Haskell,Tuples,Apply,Pointfree,我有一个表示某种状态的值元组,希望通过加法(移位)来转换它。我的值是(Int,[Int],Int]的较长版本,我希望概念上(但不是字面上)是这样的: shift n = ??? (+n) (id, map, id) -- simple(?) 这相当于: shift n (a, b, c) = (a+n, map (+n) b, c+n) 我很乐意直接使用这个显式函数,但我想知道是否有一个更惯用的无点版本使用Applicative或Arrows或…,或者它们是否会让事情变得混乱。我认为

我有一个表示某种状态的值元组,希望通过加法(移位)来转换它。我的值是(Int,[Int],Int]的较长版本,我希望概念上(但不是字面上)是这样的:

shift n = ??? (+n) (id, map, id)     -- simple(?)
这相当于:

shift n (a, b, c) = (a+n, map (+n) b, c+n)

我很乐意直接使用这个显式函数,但我想知道是否有一个更惯用的无点版本使用Applicative或Arrows或…,或者它们是否会让事情变得混乱。我认为无点版本更清楚地显示了操作的基本结构。

将函数列表应用于值列表非常简单

zipWith ($)
由于不同大小的元组都是各自的类型,因此必须为3元组显式编写一个函数。将三元组函数应用于三元组值的一般函数如下

apply (f, g, h) (a, b, c) = (f a, g b, h c)
您必须显式地编写每个函数应用程序,因为元组没有列表的递归属性。

您可以直接编写

shift n (a,b,c) = (a+n, map (+n) b, c+n)
或者定义类似于Arrow的
(***)
(&&&)
的新组合词

然后打电话

prod3 ( (+n), map (+n), (+n) ) (a,b,c)
甚至(具有适当设置的运算符优先顺序)

或者,如果您将三元组编写为嵌套对,您可以使用

Prelude Control.Arrow> ( (+5) *** map (+5) *** (+5) ) (1,([2,3],4))
(6,([7,8],9))
所以对于嵌套对

shift' :: (Num b) => b -> (b, ([b], b)) -> (b, ([b], b))
shift' n = ( (+n) *** map (+n) *** (+n) )

(另请参见)

使用
DeriveFunctor
语言扩展,您可以编写

data MyState a = MyState a [a] a
    deriving (Functor)
派生实例如下所示

instance Functor MyState where
    fmap f (MyState a bs c) = MyState (f a) (map f bs) (f c)
现在您可以定义

shift :: MyState Int -> MyState Int
shift n = fmap (+n)

(你说你的元组甚至比
(Int,[Int],Int)
还要长,所以你可能想用记录语法定义你的状态类型。)

谢谢;我知道我可以做到这一点,也许这是“最好”的解决方案,但如果没有当前的运算符,那么最好只编写函数。我在想***的泛化。谢谢;嵌套对是一个好主意,我也尝试过,但是对于较长的状态(四个项),它是混乱的,对于这种情况并不是最好的。我想知道***的泛化,但似乎不是。当我尝试这种方法时:((+5)***map(+5)***(+5)),我想知道是否有一种简单的方法可以将常见的运算(+n)从定义中反应出来(见原始问题)。嗯,
(f***(f***)f))=(***)f(***)f=(***)f=(***)f(join(*)f)=(***)加入(***)f
。对于四元组
((a,b),(c,d))
,它将是
(join(***)join(***)f
instance Functor MyState where
    fmap f (MyState a bs c) = MyState (f a) (map f bs) (f c)
shift :: MyState Int -> MyState Int
shift n = fmap (+n)