2015-08-10 14 views
10

considerare i seguenti tipi di dati e di pattern sinonimi:modelli Combinando

{-# LANGUAGE PatternSynonyms, NamedFieldPuns #-} 

data Foo = Foo { 
     a :: Int 
    , b :: String 
    , c :: Maybe Bool 
} 

pattern Bar a b <- Foo { a, b } 
pattern Baz c <- Foo { c } 

mi piacerebbe abbinare una Foo ma ottenere tutti a, b e c. Qualcosa di simile (non valida Haskell):

showit :: Foo -> String 
showit (Bar a b & Baz c) = show a ++ b ++ show c 

Una possibilità è quella di utilizzare un ViewPattern:

dup :: a -> (a, a) 
dup a = (a, a) 

showall' :: Foo -> String 
showall' (dup -> (Bar a b, Baz c)) = show a ++ b ++ show c 

Ma questo si traduce in un messaggio di avviso non esaustivo partita. Ma sappiamo che Bar e Baz sono inconfutabili, quindi anche l'abbinamento tra loro è inconfutabile.

Come può essere espresso senza un avvertimento del compilatore?

La motivazione consiste nel disporre di sinonimi di pattern a grana fine rispetto a campi di un tipo di dati di grandi dimensioni e consentire ai chiamanti di estrarre solo i campi desiderati simili ai record con NamedFieldPuns. I sinonimi di pattern non supportano ancora la sintassi dei record, ma è in corso: https://ghc.haskell.org/trac/ghc/ticket/8582

Nel mio caso non posso esporre il costruttore dal modulo poiché sto usando il modello "smart-constructor", e quindi non posso dare i chiamanti il vantaggio del modello di registrazione corrispondente a NamedFieldPuns.

Vedere https://stackoverflow.com/a/25161749/3198498 come ispirazione. Sto cercando di estendere l'idea in quella risposta per consentire ai chiamanti di estrarre arbitrariamente i campi n di m, per un numero maggiore m.

Edit: Sembra che v'è un piuttosto ampio problema con PatternSynonyms e l'esaustività controlli: https://ghc.haskell.org/trac/ghc/ticket/10339 Questo sembra rendere i sinonimi di pattern utilizzati come estrattori di campo molto sgradevole quando si compila con gli avvisi attivati.

+0

Questo probabilmente non è quello che vuoi, ma che dire: 'modello Barz a b c <- Foo {a b c}'? –

+0

@ChristopherDumas - Spero di trovare una soluzione con un singolo pattern per campo, o un pattern con una sintassi simile a record usando nomi poiché Foo può avere 10 o più campi. La buona notizia è che il ticket 8582 è previsto per l'inclusione nella prossima versione di GHC, quindi dovremmo ottenere sinonimi di pattern con sintassi di registrazione quindi. – wrl

risposta

1

Non sono sicuro che sia utile, ma ci provo. Una di queste soluzioni sarebbe accettabile?

showit :: Foo -> String 
showit [email protected](Bar a b) = show a ++ b ++ show (c x) 

showit' :: Foo -> String 
showit' [email protected](Bar a b) = show a ++ b ++ showthat x 
    where 
    showthat (Baz c) = show c 
Problemi correlati