Je voudrais écrire une version sûre de toEnum
:toEnum sûr et polymorphes
safeToEnum :: (Enum t, Bounded t) => Int -> Maybe t
Une implémentation naïve:
safeToEnum :: (Enum t, Bounded t) => Int -> Maybe t
safeToEnum i =
if (i >= fromEnum (minBound :: t)) && (i <= fromEnum (maxBound :: t))
then Just . toEnum $ i
else Nothing
main = do
print $ (safeToEnum 1 :: Maybe Bool)
print $ (safeToEnum 2 :: Maybe Bool)
Et cela ne fonctionne pas:
safeToEnum.hs:3:21:
Could not deduce (Bounded t1) from the context()
arising from a use of `minBound' at safeToEnum.hs:3:21-28
Possible fix:
add (Bounded t1) to the context of an expression type signature
In the first argument of `fromEnum', namely `(minBound :: t)'
In the second argument of `(>=)', namely `fromEnum (minBound :: t)'
In the first argument of `(&&)', namely
`(i >= fromEnum (minBound :: t))'
safeToEnum.hs:3:56:
Could not deduce (Bounded t1) from the context()
arising from a use of `maxBound' at safeToEnum.hs:3:56-63
Possible fix:
add (Bounded t1) to the context of an expression type signature
In the first argument of `fromEnum', namely `(maxBound :: t)'
In the second argument of `(<=)', namely `fromEnum (maxBound :: t)'
In the second argument of `(&&)', namely
`(i <= fromEnum (maxBound :: t))'
Aussi bien que je comprends le message, le compilateur ne reconnaît pas que minBound
et maxBound
doit produire exactement le même type que dans le type de résultat safeToEnum
en dépit de la déclaration de type explicite (:: t
). Toute idée de comment résoudre ce problème?
Résolu
Les deux années camccann et le travail des solutions de Dave (bien que celui de Dave doit être ajustée). Merci à vous deux (mais je ne pouvais en accepter qu'un). Exemple de travail avec ScopedTypeVariables:
{-# LANGUAGE ScopedTypeVariables #-}
safeToEnum :: forall t . (Enum t, Bounded t) => Int -> Maybe t
safeToEnum i =
if (i >= fromEnum (minBound :: t)) && (i <= fromEnum (maxBound :: t))
then Just . toEnum $ i
else Nothing
Oui. Cela fonctionne aussi. Bonne idée. – sastanin
J'aime vos solutions. C'est très bien que 'r' ne soit pas réellement évalué dans' asTypeOf' (deuxième version). – sastanin
@jetxee: Eh bien, c'est certainement évalué si vous l'utilisez réellement * ... ce qui bien sûr ne se produira pas si le résultat est 'Nothing'. N'est-ce pas génial d'être paresseux? –