gpt4 book ai didi

haskell - 折叠功能列表?

转载 作者:行者123 更新时间:2023-12-03 13:11:28 27 4
gpt4 key购买 nike

我正在尝试组合列表中任意数量的数学函数。

我编写了一个将它们链接在一起的 compose 函数:

chain :: (c -> d) -> (a -> b -> c) -> a -> b -> d
g `chain` f = \a b -> g (f a b)

所以做类似的事情
let b = (*) `chain` (+) `chain` (-)

创建一个接受 a b c d 的函数,并执行 ((a − b) + c) × d
> b 2 3 4 5
> 15

我的问题是,我希望能够根据任意列表将一组这些链接在一起:
[(*),(+),(-)] 将导致 (*) `chain` (+) `chain` (-) [(*),(+),(-),(*)] 将导致 (*) `chain` (+) `chain` (-) `chain` (*)
这可能吗?我试过使用折叠但无法让它工作,因为每次应用一个元素后累加器的类型都会改变。

例如,链接在一起的三个函数的类型是:
b :: Integer -> Integer -> Integer -> Integer -> Integer

但是对于四个来说是:
b :: Integer -> Integer -> Integer -> Integer -> Integer -> Integer

如果有人能指出我正确的方向或知道解决方案,那就太好了!谢谢你。

编辑:

我的最终目标是能够做这样的事情:
getZipList $ pure (function composing * and +) <*> ZipList [1,2,3] <*> ZipList [4,5,6] 
<*> ZipList [7,8,9]

会导致:
[(1+4)*7, (2+5)*8, (3+6)*9]

最佳答案

好吧,正如您自己指出的那样,这实际上是不可能的,因为不同的列表长度(对类型系统不可见)会导致不同的类型。唯一的“可靠”方法是某种编译时列表;有各种各样的,但没有一个是真正稳定支持和易于使用的。

最简单的替代方法是也将参数作为列表。 IE。,

ifxChain :: [a->a->a] -> [a] -> a

那个很容易实现:它基本上是一个 zip 为每个函数提供第二个参数,省略第一个参数。然后通过生成的单参数函数列表折叠第一个参数:
ifxChain fs (p0:ps) = foldl' (flip ($)) p0 $ zipWith flip fs ps

您可能希望添加对长度不匹配的列表的处理,这应该是可行的、相当安全的。

如果您坚持实际可变数量的函数参数(我认为这不好!)那么您需要相当多的类型级技巧。这种可变参数函数在 printf 中最为人所知。
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}

class ChainedFunc f t where
chainIfxs :: [t->t->t] -> t -> f
chainIfxs fs i = chainIfxPre i id $ reverse fs
chainIfxPre :: t -> (t->t) -> [t->t->t] -> f

instance ChainedFunc t t where
chainIfxPre i f [] = f i

instance (ChainedFunc f t) => ChainedFunc (t->f) t where
chainIfxPre i fin (f:fs) x0 = chainIfxPre i (flip f x0 . fin) fs

显然,这在很多方面都不好。但是,好吧,它有效……嗯……

Main> chainIfxs [(*),(+),(-)] (2 :: Int) (3 :: Int) (4 :: Int) (5 :: Int) :: Int
15

关于haskell - 折叠功能列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22824904/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com