2015-08-10 17 views
10

Rozważmy następujące rodzaje danych i sygnatur synonimy:Łączenie wzorów

{-# 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 } 

Chciałbym dopasować Foo jednak uzyskać wszystkie a, b i c. Coś jak ten (nieprawidłowy Haskell):

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

Jedną z opcji jest użycie ViewPattern:

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

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

Ale powoduje to niewyczerpujący ostrzeżenia meczu. Ale wiemy, że Bar i Baz są niepodważalne, więc dopasowanie każdego z nich jest również niepodważalne.

Jak można wyrazić to bez ostrzeżenia kompilatora?

Motywacją do tego jest posiadanie drobnoziarnistych synonimów wzorca na polach dużego typu danych i umożliwienie wywołującym wyodrębnienie tylko pożądanych pól podobnych do rekordów z NamedFieldPuns. Synonimy deseń nie obsługują jeszcze składni rekordów, ale to jest w pracach: https://ghc.haskell.org/trac/ghc/ticket/8582

W moim przypadku nie mogę odsłonić konstruktora z modułu, ponieważ używam wzorca "inteligentnego konstruktora", a więc nie mogę dać rozmówcy korzyści z dopasowania wzorców rekordów do NamedFieldPuns.

Zobacz inspirację jako https://stackoverflow.com/a/25161749/3198498. Próbuję rozwinąć pomysł w tej odpowiedzi, aby umożliwić dzwoniącym arbitralne wyodrębnienie pól, dla dużych rozmiarów m.

Edit: Okazuje się, że jest dość szeroki problem z PatternSynonyms i kompletności kontroli: https://ghc.haskell.org/trac/ghc/ticket/10339 Wydaje się to uczynić synonimy wzór używany jako wirówek polowych bardzo nieprzyjemne podczas kompilacji z włączonymi ostrzeżeniami.

+0

To prawdopodobnie nie jest to, co chcesz, ale co z: 'wzorem Barz a b c <- Foo {a b c}'? –

+0

@ChristopherDumas - Mam nadzieję, że uda mi się znaleźć rozwiązanie z jednym wzorcem na pole lub ze składnią przypominającą rekord, używając nazw, ponieważ Foo może mieć 10 lub więcej pól. Dobrą wiadomością jest to, że bilet 8582 jest przeznaczony do włączenia do następnej wersji GHC, więc powinniśmy uzyskać synonimy wzorcowe z zapisaną składnią. – wrl

Odpowiedz

1

Nie jestem pewien, czy to w ogóle pomocne, ale dam mu szansę. Czy któreś z tych rozwiązań byłoby do przyjęcia?

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