Tengo una función de utilidad que enumera todos los valores de un tipo que es a la vez enumerables y delimitada:Generar la lista de Entrs asociado con un tipo de enumeración
enumerate :: (Enum a, Bounded a) => [a]
enumerate = [minBound .. maxBound]
y un tipo de datos que implica la cartografía tipos enumerables a números enteros :
data Attribute a = Attribute { test :: a -> Int
, vals :: [Int]
, name :: String }
Dónde vals
es la lista de números enteros que representan todos los posibles valores enumerables. Por ejemplo, si tuviera
data Foo = Zero | One | Two deriving (Enum,Bounded)
continuación vals
habría [0,1,2]
.
Quiero ser capaz de crear estos atributos programáticamente, con solo una función que asigna un a
a un tipo enumerable, y un nombre. Algo como esto:
attribute :: (Enum b, Bounded b) => (a -> b) -> String -> Attribute a
attribute f str = Attribute (fromEnum . f) vs str
where
vs = map fromEnum enumerate
Esto no typecheck, porque no hay manera de conectar la llamada a enumerate
con el b
en la declaración de tipo. Así que pensé que podría hacer esto:
vs = map fromEnum $ enumerate :: [b]
pero eso no compila bien - el compilador cambia el nombre que b
-b1
. He tratado de ser más inteligente, utilizando la extensión GADTs:
attribute :: (Enum b, Bounded b, b ~ c) => {- ... -}
vs = map fromEnum $ enumerate :: (Enum c,Bounded c) => [c]
pero de nuevo, la c
se cambia el nombre a c1
.
no quiero incluir el tipo de b
como parámetro en el tipo Attribute
(principalmente porque quiero almacenar listas de atributos potencialmente con diferentes valores de b
- Por eso test
tiene por tipo a -> Int
y vals
tiene por tipo [Int]
)
¿Cómo puedo escribir este código para que haga lo que quiero que haga?
Scoped variables de tipo funciona perfecly, gracias! –
Además, esta es la primera vez que veo 'undefined' utilizado para realizar una tarea útil. –
@ChrisTaylor: Por supuesto, puede utilizar una especialización diferente de 'const', como' asTypeOf2 :: [b] -> (a -> b) -> [b] 'y luego puede escribir' enumerate \ 'asTypeOf2 \ 'f', pero probablemente no valga la pena el esfuerzo. – Vitus