arrays haskell repa

arrays - ¿Repa matrices indexadas por un tipo de datos acotados?



haskell (1)

Puede crear una instancia de forma para un envoltorio alrededor de su enumeración limitada. No estoy seguro de que esta sea la mejor manera, pero creo que hace lo que quieres.

{-# LANGUAGE ScopedTypeVariables #-} import Data.Array.Repa

Aquí hacemos una instancia de forma sobre cosas limitadas. Necesitamos un final de índice para matrices "completas".

data Idx a = Idx a | EOI deriving (Eq, Ord, Show) fromIdx :: forall a . (Bounded a, Enum a) => Idx a -> Int fromIdx EOI = fromEnum (maxBound :: a) - fromEnum (minBound :: a) + 1 fromIdx (Idx x) = fromEnum x - fromEnum (minBound :: a) toIdx :: forall a . (Bounded a, Enum a) => Int -> Idx a toIdx i | i < 0 = error "negative index" toIdx i = case compare i range of LT -> Idx $ toEnum (i + fromEnum (minBound :: a)) EQ -> EOI GT -> error "out of range" where range = fromEnum (maxBound :: a) - fromEnum (minBound :: a) + 1 instance (Bounded a, Enum a, Ord a) => Shape (Idx a) where rank _ = 1 zeroDim = Idx minBound unitDim = Idx $ succ minBound intersectDim EOI n = n intersectDim n EOI = n intersectDim (Idx n1) (Idx n2) = Idx $ min n1 n2 addDim = error "undefined" size = fromIdx sizeIsValid _ = True toIndex _ n = fromIdx n fromIndex _ i = toIdx i inShapeRange _ _ EOI = error "bad index" inShapeRange n1 n2 n = n >= n1 && n <= n2 listOfShape n = [fromIdx n] shapeOfList [i] = toIdx i shapeOfList _ = error "unsupported shape" deepSeq (Idx n) x = n `seq` x deepSeq _ x = x

Con eso, la parte de la boleta es fácil y limpia:

data C = A | F | L deriving (Eq, Enum, Ord, Bounded, Show) data Ballot c = Ballot { vote :: Array U (Idx c) Int } deriving Show mkBallot :: (Eq c, Enum c, Ord c, Bounded c, Show c) => c -> Ballot c mkBallot c = Ballot $ fromListUnboxed EOI vec where vec = map (fromEnum . (== c)) [minBound .. maxBound]

Quiero lograr algo similar a las matrices delimitadas en el paquete de matrices estándar pero utilizando matrices de repa.

¿Cuál es la manera agradable y limpia de lograr esto?

Esto es lo que intenté, pero debe haber una mejor manera que envolver todo en funciones personalizadas que verifiquen los límites:

import Data.Array.Repa data C = A | F | L deriving (Eq,Enum,Ord,Bounded,Show) data Ballot c = Ballot { vote::Array U (Z :. Int) Int } deriving Show mkBallot::(Eq c ,Enum c,Ord c, Bounded c, Show c) => c -> Ballot c mkBallot c = Ballot $ fromListUnboxed (Z :. max) (genSc c) where max = (fromEnum (maxBound `asTypeOf` c)) + 1 genSc::(Eq c,Enum c,Ord c,Bounded c,Show c) => c -> [Int] genSc c = [ f x | x <- enumFrom (minBound `asTypeOf` c) , let f v = if x == c then 1 else 0] showScore c b = index (vote b) (Z :. ((fromEnum c)))

También he intentado derivar una instancia de Shape para (sh:. C) pero, en vano, no puedo entender cómo implementar algunas de las interfaces declaradas en la clase Shape para mi tipo de datos. Estoy escribiendo la pregunta con la esperanza de que alguien más tenga alguna forma, pero si no, lo intentaré de nuevo. ¡Gracias!