2017-11-02 3 views
3

Ich bin neu bei Haskell und ich möchte in der Lage sein, einen neuen Typ, so dass ich sagen kann, was ist, aber ich muss es auch aus einer Zeichenfolge lesen. Ich habeHaskell Instanz lesen für newtype das ist nur ein int

newtype SpecialId Int 
    deriving (Eq, Ord, Show) 

ich read "5" :: SpecialId in der Lage sein wollen, wenn ich lesen in der newtype ableiten funktioniert es nicht funktioniert es nur auf read "SpecialId 5" :: SpecialId. Ich habe

versucht
instance Read SpecialId where 
    readsPrec _ s = read s 

Aber das gibt mir

SpecialId *** Exception: Prelude.read: no parse 
+0

Sie fragen Haskell, dass 'lesen', liest ein' [(SpecialId, String)] ', und dies schlägt fehl, da es nicht mit einem '' ['' char beginnt. –

+3

Ihre Syntax zum Definieren des neuen Typs ist falsch; es sollte 'newtype SpecialId = SpecialId Int abgeleitet werden (Eq, Ord, Show)'. – chepner

Antwort

8

Dies ist möglich, da GHC 8.2 -XDerivingStrategies mit:

{-# LANGUAGE GeneralizedNewtypeDeriving #-} 
{-# LANGUAGE DerivingStrategies   #-} 

newtype SpecialId = SpecialId Int 
    deriving stock (Eq, Ord, Show) 
    deriving newtype Read 

In GHCI:

ghci> read "5" :: SpecialId 
SpecialId 5 
5

Sie don‘ t brauche eine Sprache ext ension, wenn Sie bereit sind, auf die Int Instanz weiterleiten manuell:

instance Read SpecialId where 
    readsPrec n s = [ (SpecialId x, y) | (x, y) <- readsPrec n s ] 

Entgegen allem Anschein ist dies nicht eine rekursive Verwendung von readsPrec: Wir nennen die Int Version von readsPrec eine Liste von (Int, String) Paare zu bekommen, dann verwenden wir ein Listenverständnis, um alle Int in eine SpecialId zu wickeln.