Tôi đã thực hiện một chức năng tương tự như array
của numpy. Nó chuyển đổi danh sách này để các mảng, danh sách của danh sách này để mảng 2ngày vvGia đình loại Haskell và đối số giả
Nó hoạt động như thế này:
ghci> arrFromNestedLists ["hello", "world"] :: Array (Int, (Int,())) Char
array ((0,(0,())),(1,(4,()))) [((0,(0,())),'h'),((0,(1,())),'e'),((0,(2,())),'l'),((0,(3,())),'l'),((0,(4,())),'o'),((1,(0,())),'w'),((1,(1,())),'o'),((1,(2,())),'r'),((1,(3,())),'l'),((1,(4,())),'d')]
(Int, (Int,()))
và không (Int, Int)
bởi vì tôi không biết một cách programatic để tăng chiều dài của một tuple. (câu hỏi phụ: có cách nào không?)
Mã hóa của nó là khó xử và tôi phải thực hiện "giải pháp thay thế" (chuyển qua các đối số giả cho hàm) để nó hoạt động. Tôi tự hỏi nếu có một cách tốt hơn.
Vì vậy, đây là mã, bị gián đoạn với các chi tiết của các biện pháp khắc phục xấu xí:
{-# LANGUAGE FlexibleInstances, ScopedTypeVariables, TypeFamilies #-}
type family ListOfIndex i a
type instance ListOfIndex() a = a
type instance ListOfIndex (Int, i) a = [ListOfIndex i a]
class Ix i => ArrConv i where
acBounds :: a -> ListOfIndex i a -> (i, i)
acFlatten :: i -> ListOfIndex i a -> [a]
acBounds
"nên" được :: ListOfIndex i a -> (i, i)
. Và tương tự cho acFlatten
. Mỗi được đưa ra một biến giả (undefined
luôn là giá trị nhất định) vì nếu không tôi không thể có được nó để biên dịch :(
arrFromNestedLists :: forall i a. ArrConv i => ListOfIndex i a -> Array i a
arrFromNestedLists lst =
listArray
(acBounds (undefined :: a) lst)
(acFlatten (undefined :: i) lst)
Trên đây là hình nộm undefined
luận qua tại nơi làm việc. Nó kể về GHC mà thể hiện của ListOfIndex
để sử dụng.
instance ArrConv() where
acBounds _ = const ((),())
acFlatten _ = (: [])
hàm dưới đây cần phải có được sự acBounds
chức năng trong một thể hiện của ArrConv
, và được khai báo bên ngoài chỉ vì tôi cần phải sử dụng ScopedTypeVariables
và tôi không biết làm thế nào tôi có thể làm điều đó trong một trong một định nghĩa cá thể ..
acSucBounds
:: forall a i. ArrConv i
=> a -> [ListOfIndex i a] -> ((Int, i), (Int, i))
acSucBounds _ lst =
((0, inStart), (length lst - 1, inEnd))
where
(inStart, inEnd) = acBounds (undefined :: a) (head lst)
instance ArrConv i => ArrConv (Int, i) where
acBounds = acSucBounds
acFlatten _ = concatMap (acFlatten (undefined :: i))
"Tôi không biết cách có lập trình để tăng độ dài của bộ túp". Tôi không nghĩ bạn có thể. Đó là một ví dụ hoàn hảo về một hàm có kiểu phụ thuộc vào một giá trị. Nó sẽ được dễ dàng để làm trong một ngôn ngữ phụ thuộc gõ như 'Agda', nhưng không thể trong Haskell. Có lẽ bạn có thể sử dụng 'GADTs' theo cách nào đó để cho bạn một số hành vi phụ thuộc, nhưng ngoài đỉnh đầu của tôi, tôi không biết làm thế nào. –
Có thể Mẫu Haskell có thể hữu ích: http://www.haskell.org/bz/thdoc.htm http://www.haskell.org/haskellwiki/Template_Haskell – primodemus
@primodemus: Với TH tôi có thể tạo phiên bản cho 'ArrConv' cho các mảng có tối đa 10 thứ nguyên và chúng sẽ sử dụng các bộ dữ liệu bình thường cho các chỉ mục, đó là một sự cải tiến.Nhưng tôi sẽ cảm thấy giới hạn là tùy ý và mã có lẽ sẽ ít dễ đọc hơn. – yairchu