Vào Haskell, tôi đang cố gắng tái tạo một cái gì đó như định hình lại của numpy với các danh sách. Cụ thể, đưa ra một danh sách phẳng, định hình lại nó thành một danh sách n chiều:
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]]])
Tôi đã có thể tái tạo hành vi với các chỉ số cố định, ví dụ:
*Main> reshape23 [1..18]
[[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]],[[13,14,15],[16,17,18]]]
Mã của tôi là:
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
Bây giờ, tôi dường như không thể tìm ra cách để khái quát hóa điều này thành một hình dạng tùy ý. Ý tưởng ban đầu của tôi là thực hiện một lần:
reshape :: (Integral n) => [n] -> [a] -> [b]
reshape ns list = foldr (\n acc -> (chunks n) . acc) id ns list
Nhưng, bất kể tôi đi như thế nào, tôi luôn gặp lỗi loại từ trình biên dịch. Theo hiểu biết của tôi, vấn đề là tại một thời điểm nào đó, loại acc
được suy ra id
là nghĩa của a -> a
nó, và nó không giống như thực tế là danh sách các hàm trong nếp gấp đều có loại khác nhau (mặc dù tương thích với bố cục) Chữ ký. Tôi gặp vấn đề tương tự khi cố gắng thực hiện điều này với đệ quy thay vì một lần. Đây nhầm lẫn tôi vì ban đầu tôi đã có ý định cho [b]
trong reshape
's chữ ký kiểu là một stand-in cho 'khác, loại phân ly' đó có thể là bất cứ điều gì từ [[a]]
đến [[[[[a]]]]]
.
Làm thế nào tôi đi sai về điều này? Có cách nào để thực sự đạt được hành vi mà tôi dự định, hoặc chỉ đơn giản là sai khi muốn loại hành vi "năng động" này ngay từ đầu?
(..)
giaimport Data.Proxy (Proxy(..))
?