Angenommen, ich möchte Subtypen, die bestimmte Invarianten erfüllen, ohne Hilfe externer Tools wie LiquidHaskell konstruieren (idealerweise möchte ich dies auch ohne Typklassen tun). Was ist der eleganteste Weg, es zu tun? Bisher habe ich versucht, die folgenden:Validierung auf Typenebene
class Validated a where
type Underlying a
validate :: Underlying a -> Bool
construct :: Underlying a -> a
use :: a -> Underlying a
makeValidated :: Validated a => Underlying a -> Maybe a
makeValidated u = if validate u
then Just (construct u)
else Nothing
newtype Name = Name String
instance Validated Name where
type Underlying Name = String
validate str = and [ isUppercase (str !! 0)
, all isLetter str ]
construct = Name
use (Name str) = str
Ich gehe davon aus, dass, wenn ich nicht exportieren „Name“ Konstruktor aus dem Modul, ich werde eine funktionierende Lösung, weil der einzige Weg, ein Element des Typs zu konstruieren wäre durch makeValidated Funktion.
jedoch beklagt Compiler als solche:
Could not deduce (Underlying a0 ~ Underlying a)
from the context (Validated a)
bound by the type signature for
makeValidated :: Validated a => Underlying a -> Maybe a
at validated.hs:11:18-55
NB: `Underlying' is a type function, and may not be injective
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
In the first argument of `validate', namely `u'
In the expression: validate u
In the expression:
if validate u then Just (construct u) else Nothing
Wie kann ich das Problem beheben?
Ich habe versucht, meinen Code wie folgt zu ändern, aber ich bin immer die gleiche Fehlermeldung. Was mache ich falsch? 'Daten Proxy a = Proxy' ' '' Klasse Validierte ein where' 'Typ Basiswert a' ' bestätigen :: Proxy a -> Basiswert a -> Bool' 'konstruieren :: a Basiswert -> a ' ' verwenden :: a -> Underlying a' '' makeValidated :: Validiert a => Basis ein -> Vielleicht ein ' ' makeValidated u = wenn validiere (Proxy :: Proxy a) u' 'dann Just (Konstruiere u) ' ' else Nothing' – NioBium
@NioBium Du brauchst 'makeValidated :: forall a. Validiert a => ... 'und aktiviert die Spracherweiterung' ScopedTypeVariables'. Wahrscheinlich wäre eine bessere Wahl, "validate, construct" aus Ihrer Klasse zu entfernen und 'makeValidated' stattdessen in der Klasse hinzuzufügen. – chi