复制Numpy';s在Haskell中的高级索引/切片

复制Numpy';s在Haskell中的高级索引/切片,haskell,numpy,recursion,polymorphism,composition,Haskell,Numpy,Recursion,Polymorphism,Composition,Numpy在其阵列访问操作符中具有复杂的索引/切片/步进功能。见此: 在使用Haskell进行实验时,我认为尝试复制此索引功能的一个子集是有教育意义的。特别是“元组选择对象”或n维投影“() 基本上你可以做到: two_d_array[0:1:1, 0:4:2] 这将为您提供第一行stepped by 1,其中包含前2列stepped by 2(跳过1列) 为了更好地理解单词,它可以将一个原始的二维数组投影到一个更小的二维数组中。结果仍然是一个二维数组 这就是我在哈斯克尔的尝试 此类函数的类型

Numpy在其阵列访问操作符中具有复杂的索引/切片/步进功能。见此:

在使用Haskell进行实验时,我认为尝试复制此索引功能的一个子集是有教育意义的。特别是“元组选择对象”或n维投影“()

基本上你可以做到:

two_d_array[0:1:1, 0:4:2]
这将为您提供第一行stepped by 1,其中包含前2列stepped by 2(跳过1列)

为了更好地理解单词,它可以将一个原始的二维数组投影到一个更小的二维数组中。结果仍然是一个二维数组

这就是我在哈斯克尔的尝试

此类函数的类型应类似于:

(!!!) :: (Functor f) =>  f a -> [(Int, Int, Int)] -> f a
three_d_tensor !!! [(s1,e1,st1), (s2,e2,st2), (s3,e3,st3)]
所以你可以看到这样的东西:

(!!!) :: (Functor f) =>  f a -> [(Int, Int, Int)] -> f a
three_d_tensor !!! [(s1,e1,st1), (s2,e2,st2), (s3,e3,st3)]
其中,sx、ex、stx分别为开始、结束和步骤

该示例应将原始张量投影为较小的张量,第一个维度由
s1到e1限制,第二个维度由
s2到e2限制,第二个维度由st2限制等等

下面是我得到的:

slicing from to xs = take (to - from + 1) (drop from xs)

stepping n = map head . takeWhile (not . null) . iterate (drop n)

(!!!) tensor ((start, end, step):tail) = 
    project (stepSlice start end step tensor) tail map
    where 
        project tensor ((start, end, step):tail) projection = 
            project (projection (stepSlice start end step) tensor) tail (projection . map)
        project tensor [] _ = 
            tensor
        stepSlice start end step tensor = 
            ((stepping step) . (slicing start end)) tensor
由于“多态递归”的问题,上述方法不起作用。基本上我不能无限组合
map
函数,具体的表达式是
(projection.map)
。如果这种多态递归是可能的,我相信它会起作用。但我愿意接受不涉及多态递归的替代实现

我已经研究过这个问题,但仍然有不足之处:


已经有一种从现有值计算新值的类型-函数。假设我们有一个索引到结构中的函数,我们可以通过将它应用到结构中来使用它来索引结构

(!!!) = flip ($)

infixr 2 !!!
如果我们有一个索引结构的函数和另一个索引任何嵌套结构的函数,我们可以通过
fmap
将第二个函数放在结构上,然后应用外部函数将它们组合在一起

(!.) :: Functor f => (f b -> g c) -> (a -> b) -> f a -> g c
t !. f = t . fmap f

infixr 5 !.
以三维结构为例

three_d_tensor :: [[[(Int,Int,Int)]]]
three_d_tensor = [[[(x, y, z) | z <- [0..4]] | y <- [0..3]] | x <- [0..2]]
导致

[[[(1,0,1),(1,0,3)],[(1,2,1),(1,2,3)]],[[(2,0,1),(2,0,3)],[(2,2,1),(2,2,3)]]]

张量不是函子(嵌套或其他).是的,有时假装这样做是可行的,但这是EKmett弄错的一件事,我想。-你真的需要运行时变量秩吗?请注意,你可以使用多态递归…前提是1)函数的类型实际上是语法上可表达的,2)你提供了显式类型签名。我不知道这两者是否相关,但它们看起来很有趣:@Bakuriu你是说这个吗:哇。这真的很棒。你把所有的维度投影组合在一起。
,然后用
!!!
。我注意到了与正常组合的平行性
(fB->fC)->(fA->fB)->fa->fc
类似于
(::(b->c)->(a->b)->a->c
。但是这种“嵌套”构图是在函子的内容中进行的。我还注意到,您使用
g
来允许对函子本身进行更改?这种转换叫什么?“嵌套构图”?“主要区别在于,我的初衷是获取一个投影列表,它的优点是允许根据某个运行时值确定任意投影。当前表单只能在编译时确定投影。但运行时元编程或类型类黑客或依赖类型可能允许基于列表的投影;这就是部分应用程序和lambda所做的。在编译时需要完成的唯一部分是检查投影是否正确。