On 2014-11-26 at 13:31:28 +0100, Herbert Valerio Riedel wrote:
[...]
> ...too bad bidirectional PatternSynonyms require -XPatternSynonyms to be
> enabled in code using them as value constructors...
>
> otherwise we could put them to use to smooth a transition to
> an opaque `Version`... as on the outside it would behave just as if it
> was really just
>
> data Version = Version [Int]
>
> but the pattern-synonyms would translate that back/forth into the
> internal opaque representation...
I got that one backward; it's when you actually use a pattern-syn for
pattern-matching that you need `-XPatternSynonyms` (see GHCi example below)
...to follow-up on this idea, here's some proof-of-concept code:
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
module Version (Version, pattern Version, versionBranch) where
-- import Data.Version
data VersionImpl = V0
| V1 !Int
| V2 !Int !Int
| V3p !Int !Int !Int [Int]
deriving (Show,Eq)
-- TODO: proper 'Show' instance & others
makeVersion :: [Int] -> Version
makeVersion [] = V0
makeVersion [a] = V1 a
makeVersion [a,b] = V2 a b
makeVersion (a:b:c:ds) = V3p a b c ds
-- | Backward compat field-accessor function
versionBranch :: Version -> [Int]
versionBranch V0 = []
versionBranch (V1 a) = [a]
versionBranch (V2 a b) = [a,b]
versionBranch (V3p a b c ds) = (a:b:c:ds)
type Version = VersionImpl
pattern Version :: [Int] -> Version
pattern Version v <- (versionBranch -> v) where
Version v = makeVersion v
when compiled, this mostly like if it was merely defined as
data Version = Version [Int]
deriving ...
makeVersion :: [Int] -> Version
makeVersion = Version
e.g.:
GHCi, version 7.9.20141124:
http://www.haskell.org/ghc/ :? for help
Ok, modules loaded: Version.
λ:2> :browse
pattern Version :: [Int] -> Version
type Version = Version.VersionImpl
versionBranch :: Version -> [Int]
λ:3> Version [1]
V1 1
it :: Version
λ:4> Version [1,2,3,4]
V3p 1 2 3 [4]
it :: Version
λ:5> let v23 = Version [2,3]
v23 :: Version
λ:6> case v23 of Version x -> x
<interactive>:6:13:
A pattern match on a pattern synonym requires PatternSynonyms
In the pattern: Version x
In a case alternative: Version x -> x
In the expression: case v23 of { Version x -> x }
λ:7> :set -XPatternSynonyms
λ:8> case v23 of Version x -> x
[2,3]
it :: [Int]
So the only thing that's unfortunate is the need to enable
-XPatternSynonyms at use-sites, otherwise this would almost seem perfect
for Duncan's use-case...
Cheers,
hvr