Al entrar en Haskell, estoy tratando de reproducir algo como la remodelación de Numpy con listas. Específicamente, dada una lista plana, reconfórmela en una lista n-dimensional:
import numpy as np
a = np.arange(1, 18)
b = a.reshape([-1, 2, 3])
# b =
#
# array([[[ 1, 2, 3],
# [ 4, 5, 6]],
#
# [[ 7, 8, 9],
# [10, 11, 12]],
#
# [[13, 14, 15],
# [16, 17, 18]]])
Pude reproducir el comportamiento con índices fijos, por ejemplo:
*Main> reshape23 [1..18]
[[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]],[[13,14,15],[16,17,18]]]
Mi código es:
takeWithRemainder :: (Integral n) => n -> [a] -> ([a], [a])
takeWithRemainder _ [] = ([], [])
takeWithRemainder 0 xs = ([], xs)
takeWithRemainder n (x:xs) = (x : taken, remaining)
where (taken, remaining) = takeWithRemainder (n-1) xs
chunks :: (Integral n) => n -> [a] -> [[a]]
chunks _ [] = []
chunks chunkSize xs = chunk : chunks chunkSize remainderOfList
where (chunk, remainderOfList) = takeWithRemainder chunkSize xs
reshape23 = chunks 2 . chunks 3
Ahora, parece que no puedo encontrar una manera de generalizar esto a una forma arbitraria. Mi idea original era hacer un pliegue:
reshape :: (Integral n) => [n] -> [a] -> [b]
reshape ns list = foldr (\n acc -> (chunks n) . acc) id ns list
Pero, no importa cómo lo haga, siempre obtengo un error de tipo del compilador. Según tengo entendido, el problema es que en algún momento, accse infiere que el tipo para es idie a -> a, y no le gusta el hecho de que la lista de funciones en el pliegue tiene un tipo diferente (aunque compatible para la composición) firma. Me encuentro con el mismo problema tratando de implementar esto con recursividad yo mismo en lugar de un pliegue. Esto me confunde porque originalmente me había propuesto para el [b]de reshape's firma de tipo a ser un sustituto de 'otra, de tipo disociado' que podría ser cualquier cosa de [[a]]a [[[[[a]]]]].
¿Cómo me estoy equivocando sobre esto? ¿Hay alguna manera de lograr realmente el comportamiento que pretendía, o es simplemente incorrecto querer este tipo de comportamiento "dinámico" en primer lugar?
(..)parte estáimport Data.Proxy (Proxy(..))?