Entrando em Haskell, estou tentando reproduzir algo como a remodelação de numpy com listas. Especificamente, dada uma lista simples, reformule-a em uma 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]]])
Consegui reproduzir o comportamento com índices fixos, por exemplo:
*Main> reshape23 [1..18]
[[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]],[[13,14,15],[16,17,18]]]
Meu código é:
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
Agora, parece que não consigo encontrar uma maneira de generalizar isso para uma forma arbitrária. Minha ideia original era fazer uma dobra:
reshape :: (Integral n) => [n] -> [a] -> [b]
reshape ns list = foldr (\n acc -> (chunks n) . acc) id ns list
Mas, não importa como eu faça isso, sempre recebo um erro de tipo do compilador. Pelo que entendi, o problema é que, em algum momento, o tipo for acc
é inferido como id
ie a -> a
, e não gosta do fato de que a lista de funções na dobra tem um tipo diferente (embora compatível com a composição) assinatura. Eu me deparo com o mesmo problema tentando implementar isso com recursão em vez de uma dobra. Isso me confundiu porque originalmente eu tinha pretendido para o [b]
em reshape
's assinatura de tipo para ser um stand-in para 'um outro, tipo dissociada', que poderia ser qualquer coisa, desde [[a]]
a [[[[[a]]]]]
.
Como estou indo errado sobre isso? Existe uma maneira de realmente alcançar o comportamento que eu pretendia, ou é simplesmente errado querer esse tipo de comportamento "dinâmico" em primeiro lugar?
(..)
parteimport Data.Proxy (Proxy(..))
?