2016-06-23 1 views
-2

Используя одну неподвижную структуру, мы можем написатьПравильный способ обобщения полей данных на основе перечисленной типа

data Stats = Stats { lines :: !Int, words :: !Int } 

instance Num Stats where 
    fromInteger x = Stats x x 
    (Stats a b) + (Stats a' b') = Stats (a + a') (b + b') 

мы можем создать некоторую динамическую структуру для достижения обобщенной версии

newtype Stats a = Stats { unStats :: [Int] } -- or Map, Vector, ... 

instance forall a . (Enum a, Bounded a) => Num (Stats a) where 
    fromInteger = Stats . replicate sz 
        where sz = fromEnum (maxBound::a) - fromEnum (minBound::a) + 1 
    (Stats a) + (Stats b) = Stats $ zipWith (+) a b 

(¨) :: forall a . (Eq a, Enum a, Bounded a) => Int -> a -> Stats a 
x ¨ u = Stats $ map (\k -> if k == u then x else 0) [minBound .. maxBound :: a] 

и использовать в качестве

data TextStats = Lines | Words deriving (Eq, Ord, Enum, Bounded) 

someTextStats :: Stats TextStats 
someTextStats = 1 ¨Lines + 5 ¨Words 

прежний способ является статическим (например, функция измерения единиц измерения будет), но а не в том смысле, что определенная структура должна быть пройдена во время выполнения.

Существует какой-то путь от шаблона Haskell? Thk!

+0

Аноним, вы можете объяснить свой -1? – josejuan

+0

Второй анонимный, вы можете объяснить свой -1? – josejuan

ответ

2

Ваш подход работает, если вы используете RankNTypes, ScopedVariables и вы не пытаетесь использовать двойные кавычки в качестве имени оператора:

{-# LANGUAGE RankNTypes, ScopedTypeVariables #-} 

newtype Stats a = Stats { unStats :: [Integer] } -- or Map, Vector, ... 
    deriving (Show) 

instance forall a . (Enum a, Bounded a) => Num (Stats a) where 
    fromInteger = Stats . replicate sz 
        where sz = fromEnum (maxBound::a) - fromEnum (minBound::a) + 1 
    (Stats a) + (Stats b) = Stats $ zipWith (+) a b 

(€) :: forall a . (Eq a, Enum a, Bounded a) => Integer -> a -> Stats a 
x € u = Stats $ map (\k -> if k == u then x else 0) [minBound .. maxBound :: a] 

data TextStats = Lines | Words deriving (Eq, Ord, Enum, Bounded) 

test = 3 € Lines + 5 € Words 

Я также изменил список, чтобы содержать целые числа вместо Ints. Это то, что вы ищите?

+0

Мой подход работает без 'RankNTypes' и использует' '' (diaeresis). Мой * динамический * подход работает, я ищу статический ... но thk. – josejuan