Ich möchte eine sichere Version von toEnum
schreiben:Sicher und polymorphen toEnum
safeToEnum :: (Enum t, Bounded t) => Int -> Maybe t
Eine naive Implementierung:
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)
Und es funktioniert nicht:
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))'
Sowie ich die Nachricht verstehe, erkennt der Compiler nicht, dass minBound
und maxBound
sollte trotz der expliziten Typdeklaration() genau den gleichen Typ wie im Ergebnistyp safeToEnum
produzieren. Irgendeine Idee, wie man es repariert?
Gelöst
Beide camccann ist und Lösungen Arbeit Dave (obwohl Daves ein angepasst werden muss). Danke euch beiden (aber ich konnte nur einen akzeptieren). Arbeitsbeispiel mit 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
Ja. Das funktioniert auch. Gute Idee. – sastanin
Ich mag Ihre Lösungen. Es ist sehr schön, dass 'r' nicht wirklich in' asTypeOf' (zweite Version) ausgewertet wird. – sastanin
@jetxee: Nun, es ist sicherlich ausgewertet, wenn Sie es tatsächlich * benutzen * was natürlich nicht passieren wird, wenn das Ergebnis 'Nichts' ist. Ist es nicht toll, faul zu sein? –