2012-10-19 15 views
19

Chcę osiągnąć coś podobnego do ograniczonych tablic w standardowym pakiecie tablicowym, ale używając tablic repa.Repa tablice indeksowane przez ograniczony typ danych?

Jaki jest miły i czysty sposób, aby to osiągnąć?

To co próbowałem, ale nie musi być lepszy sposób niż zawijania wszystko w funkcji niestandardowych sprawdzić granice:

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))) 

także starałem się czerpać instancji kształt (SH. C), ale bezskutecznie, nie mogę naprawdę zrozumieć, jak zaimplementować niektóre interfejsy zadeklarowane w klasie Shape dla mojego typu danych. Piszę to pytanie z nadzieją, że ktoś inny ma sposób, ale jeśli nie, spróbuję jeszcze raz. Dziękuję Ci!

Odpowiedz

2

Możesz utworzyć instancję kształtu dla otoki wokół ograniczonego wyliczenia. Nie jestem pewien, czy to najlepszy sposób, ale wydaje mi się, że robi to, co chcesz.

{-# LANGUAGE ScopedTypeVariables #-} 

import Data.Array.Repa 

Tutaj robimy instancję kształtu nad ograniczonymi rzeczami. Potrzebujemy końcowego indeksu dla "pełnych" tablic.

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 

Z tym, część głosowanie jest łatwe i czyste:

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] 
+0

będę spojrzeć na to. – user1105045

Powiązane problemy