Skip to content

Instantly share code, notes, and snippets.

@rwbarton
Forked from 23Skidoo/A.hs
Last active February 2, 2017 09:32
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rwbarton/dd8e51dce2a262d17a80 to your computer and use it in GitHub Desktop.
Save rwbarton/dd8e51dce2a262d17a80 to your computer and use it in GitHub Desktop.
-- Code taken from http://stackoverflow.com/questions/12735274/breaking-data-set-integrity-without-generalizednewtypederiving/12744568#12744568
-- Discussion on haskell-cafe: http://thread.gmane.org/gmane.comp.lang.haskell.cafe/100870
-- http://www.haskell.org/pipermail/haskell-cafe/2012-October/103984.html
-- Modified to remove orphan instances by rwbarton
module A where
data U = X | Y deriving (Eq, Ord, Show)
data T u b c = T u b c deriving (Eq, Show)
{-# LANGUAGE FlexibleInstances #-}
module B where
import Data.Monoid ((<>))
import Data.Set
import A
data MB = MB deriving (Eq, Ord, Show)
instance Ord c => Ord (T U MB c) where
compare (T u1 b1 c1) (T u2 b2 c2) = compare u1 u2 <> compare b1 b2 <> compare c1 c2
ins :: Ord c => T U MB c -> Set (T U MB c) -> Set (T U MB c)
ins = insert
{-# LANGUAGE FlexibleInstances #-}
module C where
import Data.Monoid ((<>))
import Data.Set
import A
data MC = MC deriving (Eq, Ord, Show)
instance Ord b => Ord (T U b MC) where
compare (T u1 b1 c1) (T u2 b2 c2) = compare u2 u1 <> compare b1 b2 <> compare c1 c2
ins' :: Ord b => T U b MC -> Set (T U b MC) -> Set (T U b MC)
ins' = insert
module Main where
import Data.Set
import A
import B
import C
test :: Set (T U MB MC)
test = ins' (T X MB MC) $ ins (T X MB MC) $ ins (T Y MB MC) $ empty
main :: IO ()
main = print test
rwbarton@morphism:/tmp/3854294$ ghc -Wall -XSafe -fforce-recomp --make D.hs
[1 of 4] Compiling A ( A.hs, A.o )
[2 of 4] Compiling B ( B.hs, B.o )
[3 of 4] Compiling C ( C.hs, C.o )
[4 of 4] Compiling Main ( D.hs, D.o )
Linking D ...
rwbarton@morphism:/tmp/3854294$ ./D
fromList [T X MB MC,T Y MB MC,T X MB MC]
@23Skidoo
Copy link

With -XIncoherentInstances it works even when all code is in a single file:

{-# LANGUAGE FlexibleInstances, IncoherentInstances, Safe #-}
module Test
       where

import Data.Monoid ((<>))
import Data.Set

data U = X | Y deriving (Eq, Ord, Show)
data T u b c = T u b c deriving (Eq, Show)

data MB = MB deriving (Eq, Ord, Show)

instance Ord c => Ord (T U MB c) where
  compare (T u1 b1 c1) (T u2 b2 c2) = compare u1 u2 <> compare b1 b2 <> compare c1 c2

ins :: Ord c => T U MB c -> Set (T U MB c) -> Set (T U MB c)
ins = insert

data MC = MC deriving (Eq, Ord, Show)

instance Ord b => Ord (T U b MC) where
  compare (T u1 b1 c1) (T u2 b2 c2) = compare u2 u1 <> compare b1 b2 <> compare c1 c2

ins' :: Ord b => T U b MC -> Set (T U b MC) -> Set (T U b MC)
ins' = insert

test :: Set (T U MB MC)
test = ins' (T X MB MC) $ ins (T X MB MC) $ ins (T Y MB MC) $ empty

Output:

*Test> test
Loading package array-0.5.0.0 ... linking ... done.
Loading package deepseq-1.3.0.2 ... linking ... done.
Loading package containers-0.5.5.1 ... linking ... done.
fromList [T X MB MC,T Y MB MC,T X MB MC]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment