문제
나는 Numpy 's와 비슷한 기능을 만들었습니다 array
. 목록을 배열로 변환하고 목록 목록을 2D 어레이 등으로 변환합니다.
다음과 같이 작동합니다.
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, ()))
그리고 아닙니다 (Int, Int)
튜플의 길이를 늘리는 프로그래밍 방식을 모르기 때문입니다. (측면 질문 : 그런 길이 있습니까?)
그것의 코딩은 어색했고 나는 그것이 작동하기 위해 "더미 논쟁을 전달하는"(더미 논쟁을 전달)해야했다. 더 나은 방법이 있는지 궁금합니다.
추악한 해결 방법에 대한 세부 사항이 중단되는 코드는 다음과 같습니다.
{-# 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
"해야한다 :: ListOfIndex i a -> (i, i)
. 그리고 마찬가지로 acFlatten
. 각각 더미 변수가 제공됩니다 (undefined
그렇지 않으면 나는 그것을 컴파일 할 수 없었기 때문에 :(
arrFromNestedLists :: forall i a. ArrConv i => ListOfIndex i a -> Array i a
arrFromNestedLists lst =
listArray
(acBounds (undefined :: a) lst)
(acFlatten (undefined :: i) lst)
위는 더미입니다 undefined
직장에서 통과하는 논쟁. 그것은 GHC에 어떤 인스턴스를 알려줍니다 ListOfIndex
사용.
instance ArrConv () where
acBounds _ = const ((), ())
acFlatten _ = (: [])
아래 함수는 acBounds
인스턴스에서 기능 ArrConv
, 사용해야하기 때문에 외부로 선언됩니다. ScopedTypeVariables
그리고 인스턴스 정의에서 함수에서 어떻게 할 수 있는지 모르겠습니다.
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))
해결책
ACBounds 및 Acflatten에 대한 추가 주장이 필요한 이유는 a
그리고 i
회수 할 수 없습니다 ListOfIndex i a -> (i, i)
그리고 ListOfIndex i a -> [a]
각기. 하나의 해결 방법은 두 가지 메소드를 하나의 방법으로 결합하는 것입니다. acArgs
유형의 ListOfIndex i a -> ((i, i), a)
. 이제 유일한 문제는 (Int, i)
TypEchecker가 유형을 일반화하는 것을 방지하는 방식으로 이전과 동일한 문제를 일으키는 것입니다 (예 : 단순히 사용할 수 없습니다. fst . acArgs
).
{-# LANGUAGE TypeFamilies, FlexibleInstances #-} import Data.Array 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 acArgs :: ListOfIndex i a -> ((i, i), [a]) instance ArrConv () where acArgs x = (((), ()), [x]) instance ArrConv i => ArrConv (Int, i) where acArgs lst = (((0, inStart), (length lst - 1, inEnd)), args >>= snd) where args = map acArgs lst (inStart, inEnd) = fst (head args) arrFromNestedLists :: ArrConv i => ListOfIndex i a -> Array i a arrFromNestedLists = uncurry listArray . acArgs
다른 팁
당신이 유지하고 싶다면 acBounds
그리고 acFlatten
별도로 추가 할 수 있습니다 유형 수준 태그 인수 그것에, 즉 acBounds
유형이있을 것입니다 acBounds :: Proxy a -> ListOfIndex i a -> (i, i)
. 이것은 필요를 제거합니다 undefined
당신은 단지 통과 할 수 있기 때문에 논쟁 (Proxy :: SomeConcreteType)
그것에; 그리고 acBounds
유용한 값 수준 정보를 추출 할 수있는 방법이 없습니다. 이는 단위 유형에 동형 (비 형성 된 방식)이기 때문입니다.