4FMG*OUSPEVDUJPO w )JSPNJ*4)**ʢ[email protected]ʣ w %PDUPSBM$BOEJEBUFJO.BUIFNBUJDT w 3FTFBSDI"SFB.BUIFNBUJDBM-PHJD
$PNQVUFS4DJFODF w 8SJUJOHBOEUFBDIJOH)BTLFMMGPSZFBST
newtype w "UZQFXJUIBTJOHMFDPOTUSVDUPSBOEpFME w )BTUIF4BNFSFQSFTFOUBUJPOBTJUTPOMZpFME w %JTUJOHVJTIFEGSPNUIFPSJHJOBMUZQFBUUZQF MFWFM
CVUIBTUIFTBNFNFNPSZSFQSFTFOUBUJPO BTUIFPSJHJOBM
BOEFWBMVBUFETUSJDUMZ newtype Foo α = Bar α newtype Id = MkId Word
3PMFTPGnewtypeT *NQMFNFOUBUJPO)JEJOH module Data.Id (Id ()) where newtype Id = MkId Word %JTUJOHVJTIFEBUUZQFMFWFM
CVUKVTUBWord internally )JEFEBUBDPOTMkId outside the module
3PMFTPGnewtypeT *NQMFNFOUBUJPO)JEJOH *NQMFNFOUBUJPO4IBSJOH module Data.Id (Id ()) where newtype Id = MkId Word %JTUJOHVJTIFEBUUZQFMFWFM
CVUKVTUBWord internally {-# LANGUAGE GeneralizedNewtypeDeriving #-} newtype Id = MkId Word deriving (Num, Eq) )JEFEBUBDPOTMkId outside the module
3PMFTPGnewtypeT *NQMFNFOUBUJPO)JEJOH *NQMFNFOUBUJPO4IBSJOH module Data.Id (Id ()) where newtype Id = MkId Word %JTUJOHVJTIFEBUUZQFMFWFM
CVUKVTUBWord internally {-# LANGUAGE GeneralizedNewtypeDeriving #-} newtype Id = MkId Word deriving (Num, Eq) 6OEFSJWBCMFJO)BTLFMM
CVUXFDBOTIBSFWordTJNQM )JEFEBUBDPOTMkId outside the module
3PMFTPGnewtypeT *NQMFNFOUBUJPO)JEJOH *NQMFNFOUBUJPO4IBSJOH module Data.Id (Id ()) where newtype Id = MkId Word %JTUJOHVJTIFEBUUZQFMFWFM
CVUKVTUBWord internally {-# LANGUAGE GeneralizedNewtypeDeriving #-} newtype Id = MkId Word deriving (Num, Eq) 6OEFSJWBCMFJO)BTLFMM
CVUXFDBOTIBSFWordTJNQM &WPMWFT NPSFJO %FSJWJOH7JB )JEFEBUBDPOTMkId outside the module
3PMFTPGnewtypeT *NQMFNFOUBUJPO)JEJOH *NQMFNFOUBUJPO4IBSJOH *NQMFNFOUBUJPO4FMFDUJPO module Data.Id (Id ()) where newtype Id = MkId Word %JTUJOHVJTIFEBUUZQFMFWFM
CVUKVTUBWord internally {-# LANGUAGE GeneralizedNewtypeDeriving #-} newtype Id = MkId Word deriving (Num, Eq) 6OEFSJWBCMFJO)BTLFMM
CVUXFDBOTIBSFWordTJNQM &WPMWFT NPSFJO %FSJWJOH7JB )JEFEBUBDPOTMkId outside the module
3PMFTPGnewtypeT *NQMFNFOUBUJPO)JEJOH *NQMFNFOUBUJPO4IBSJOH *NQMFNFOUBUJPO4FMFDUJPO {-# LANGUAGE GeneralizedNewtypeDeriving #-} newtype Id = MkId Word deriving (Num, Eq) 6OEFSJWBCMFJO)BTLFMM
CVUXFDBOTIBSFWordTJNQM &WPMWFT NPSFJO %FSJWJOH7JB module Data.Id (Id ()) where newtype Id = MkId Word )JEFEBUBDPOTMkId outside the module
3PMFTPGnewtypeT *NQMFNFOUBUJPO)JEJOH *NQMFNFOUBUJPO4IBSJOH *NQMFNFOUBUJPO4FMFDUJPO {-# LANGUAGE GeneralizedNewtypeDeriving #-} newtype Id = MkId Word deriving (Num, Eq) 6OEFSJWBCMFJO)BTLFMM
CVUXFDBOTIBSFWordTJNQM &WPMWFT NPSFJO %FSJWJOH7JB module Data.Id (Id ()) where newtype Id = MkId Word )JEFEBUBDPOTMkId outside the module %JTUJOHVJTIFEBUUZQFMFWFM
CVUKVTUBWord internally
.POPJET w "OPQFSBUJPOXIJDIDBOCFDPNQVUFECPUI GSPNMFGUBOESJHIU
XJUIVOJUFMFNFOU • Both `max` and (+) • … can be computed from either left or right, • … has Nothing (no max) and 0 as units. • Mapping to monoid + folding ⤳ Foldable! x ∙ (y ∙ z) = (x ∙ y) ∙ z x ∙ ε = x = ε ∙ x
'PMEBCMFDMBTT *UTV⒏DFTUPNBLFNBY
pUJOUIJTGSBNFXPSL 8FDBOIBWFBUNPTUPOFJOTUBODFGPSMonoid Word class Foldable t where foldMap :: Monoid m 㱺 (a " m) " t a " m … .BQUP.POPJE
'PMEBCMFDMBTT *UTV⒏DFTUPNBLFNBY
pUJOUIJTGSBNFXPSL 8FDBOIBWFBUNPTUPOFJOTUBODFGPSMonoid Word *NQMFNFOUBUJPO4FMFDUJPOVTJOHnewtypeT class Foldable t where foldMap :: Monoid m 㱺 (a " m) " t a " m … .BQUP.POPJE
&YBNQMFJOTUBODFT newtype Sum a = Sum { getSum :: a} deriving (Num, Integral) instance Num a 㱺 Monoid (Sum a) where (<>) = (+); ε = 0 newtype Max a = Max { getMax :: a } deriving (Num, Integral, Ord) instance Ord a 㱺 Semigroup (Max a) where (<>) = max
&YBNQMFJOTUBODFT newtype Sum a = Sum { getSum :: a} deriving (Num, Integral) instance Num a 㱺 Monoid (Sum a) where (<>) = (+); ε = 0 newtype Max a = Max { getMax :: a } deriving (Num, Integral, Ord) instance Ord a 㱺 Semigroup (Max a) where (<>) = max .POPJEPG OVNFSJDBEEJUJPO
&YBNQMFJOTUBODFT newtype Sum a = Sum { getSum :: a} deriving (Num, Integral) instance Num a 㱺 Monoid (Sum a) where (<>) = (+); ε = 0 newtype Max a = Max { getMax :: a } deriving (Num, Integral, Ord) instance Ord a 㱺 Semigroup (Max a) where (<>) = max .POPJEPG OVNFSJDBEEJUJPO 4FNJHSPVQCZ UBLJOHNBY
&YBNQMFJOTUBODFT newtype Sum a = Sum { getSum :: a} deriving (Num, Integral) instance Num a 㱺 Monoid (Sum a) where (<>) = (+); ε = 0 newtype Max a = Max { getMax :: a } deriving (Num, Integral, Ord) instance Ord a 㱺 Semigroup (Max a) where (<>) = max .POPJEPG OVNFSJDBEEJUJPO 4FNJHSPVQCZ UBLJOHNBY *NQMTIBSJOHCZ (/%
1SBDUJDBM3FNBSL w 0OMZCPVOEFEUZQFTDBOCF\max
min^NPOPJET 8F OFFENBYJNVNNJOJNVNFMFNFOUUPIBWFUIFVOJU
w 8FTUJMMIBWFB4FNJSJOH
XIJDIMBDLTVOJUT w 8FIBWFUPDPOWFSUJUUPNPOPJEUPVTFXJUI'PMEBCMF newtype Max a = Max a instance Ord a 㱺 Semigroup (Max a) instance Bounded a 㱺 Monoid (Max a)
1SBDUJDBM3FNBSL OptionBEKPJOTVOJU
UVSOJOHTFNJHSPVQTJOUPNPOPJET ʙ()$ɿ.BZCFSFRVJSFT.POPJEBBTBDPOTUSBJOU newtype Option a = Option (Maybe a) instance Semigroup a 㱺 Monoid (Option a) instance Monoid a 㱺 Monoid (Maybe a)
1SBDUJDBM3FNBSL OptionBEKPJOTVOJU
UVSOJOHTFNJHSPVQTJOUPNPOPJET ʙ()$ɿ.BZCFSFRVJSFT.POPJEBBTBDPOTUSBJOU ()$ʙɿ3FRVJSFTPOMZSemigroup a, no need of 0QUJPO newtype Option a = Option (Maybe a) instance Semigroup a 㱺 Monoid (Option a) instance Monoid a 㱺 Monoid (Maybe a) instance Semigroup a 㱺 Monoid (Maybe a)
1SBDUJDBM3FNBSL OptionBEKPJOTVOJU
UVSOJOHTFNJHSPVQTJOUPNPOPJET ʙ()$ɿ.BZCFSFRVJSFT.POPJEBBTBDPOTUSBJOU ()$ʙɿ3FRVJSFTPOMZSemigroup a, no need of 0QUJPO 8FTUJMMIBWFUPVTF0QUJPOUPXSJUFBQPSUBCMFDPEFTUIPVHI newtype Option a = Option (Maybe a) instance Semigroup a 㱺 Monoid (Option a) instance Monoid a 㱺 Monoid (Maybe a) instance Semigroup a 㱺 Monoid (Maybe a)
;FSP$PTU$PFSDJPO w $PFSDJCMFSFMBUFTUXPUZQFTXJUIUIFTBNFNFNPSZSFQS w *UTFFNTMJLFBUZQFDMBTT
CVU()$HFOFSBUFTBOJOGPSNBUJPO BUDPNQJMFUJNF
BOEVTFSDBOOPUBEEDVTUPNJOTUBODF import Data.Coerce (coerce) coerce :: Coercible a b 㱺 a " b
;FSP$PTU$PFSDJPO w $PFSDJCMFSFMBUFTUXPUZQFTXJUIUIFTBNFNFNPSZSFQS w *UTFFNTMJLFBUZQFDMBTT
CVU()$HFOFSBUFTBOJOGPSNBUJPO BUDPNQJMFUJNF
BOEVTFSDBOOPUBEEDVTUPNJOTUBODF w 8JUIcoerceGSPNData.Coerce
XFDBOEP[FSPDPTUDBTUT import Data.Coerce (coerce) coerce :: Coercible a b 㱺 a " b
;FSP$PTU$PFSDJPO w $PFSDJCMFSFMBUFTUXPUZQFTXJUIUIFTBNFNFNPSZSFQS w *UTFFNTMJLFBUZQFDMBTT
CVU()$HFOFSBUFTBOJOGPSNBUJPO BUDPNQJMFUJNF
BOEVTFSDBOOPUBEEDVTUPNJOTUBODF w 8JUIcoerceGSPNData.Coerce
XFDBOEP[FSPDPTUDBTUT w *OGFSSFEQFSNPEVMF
XFOFFEUIFJOGPPGEBUBDPOTUSVDUPS UPDBMMcoerce import Data.Coerce (coerce) coerce :: Coercible a b 㱺 a " b
$BTUJOHCXOFTUFEUZQFT *UTDPOWFOJFOUUIBUXFDBODBTUBOZOFTUFEUZQFT 3FBMMZ newtype Down a = Down a instance Ord a 㱺 Ord (Down a) where a ≤ b = b ≤ a data Heap a minView :: Heap a " Maybe a
$BTUJOHCXOFTUFEUZQFT *UTDPOWFOJFOUUIBUXFDBODBTUBOZOFTUFEUZQFT 3FBMMZ newtype Down a = Down a instance Ord a 㱺 Ord (Down a) where a ≤ b = b ≤ a data Heap a minView :: Heap a " Maybe a 3FWFSTFE0SEFS
$BTUJOHCXOFTUFEUZQFT *UTDPOWFOJFOUUIBUXFDBODBTUBOZOFTUFEUZQFT 3FBMMZ newtype Down a = Down a instance Ord a 㱺 Ord (Down a) where a ≤ b = b ≤ a data Heap a minView :: Heap a " Maybe a 3FWFSTFE0SEFS )FBQ
$BTUJOHCXOFTUFEUZQFT *UTDPOWFOJFOUUIBUXFDBODBTUBOZOFTUFEUZQFT 3FBMMZ newtype Down a = Down a instance Ord a 㱺 Ord (Down a) where a ≤ b = b ≤ a data Heap a minView :: Heap a " Maybe a 3FWFSTFE0SEFS )FBQ .JOJNVN
0
$BTUJOHCXOFTUFEUZQFT *UTDPOWFOJFOUUIBUXFDBODBTUBOZOFTUFEUZQFT 3FBMMZ newtype Down a = Down a instance Ord a 㱺 Ord (Down a) where a ≤ b = b ≤ a data Heap a minView :: Heap a " Maybe a 4FNBOUJDBMMZ
Heap a.645/05CFDBTUFEUPHeap (Down a) 3FWFSTFE0SEFS )FBQ .JOJNVN
0
3PMFT w 8FDBODBTUUIFNXJUIDPFSDF ghci> h = fromList [1,2,3] :: Heap Int ghci> minView (coerce h :: Heap (Down Int)) Just 1 w 5IFOXFTQFDJGZUIF3PMF .VTUCFJust 3!
3PMFT w 8FDBODBTUUIFNXJUIDPFSDF type role Heap nominal ghci> h = fromList [1,2,3] :: Heap Int ghci> minView (coerce h :: Heap (Down Int)) Just 1 w 5IFOXFTQFDJGZUIF3PMF .VTUCFJust 3!
3PMFT w 8FDBODBTUUIFNXJUIDPFSDF type role Heap nominal ghci> h = fromList [1,2,3] :: Heap Int ghci> minView (coerce h :: Heap (Down Int)) Just 1 w 5IFOXFTQFDJGZUIF3PMF ghci> minView (coerce h :: Heap (Down Int)) error: Couldn't match type ‘Int’ with ‘Down Int’ .VTUCFJust 3!
3PMFT w 8FDBODBTUUIFNXJUIDPFSDF type role Heap nominal ghci> h = fromList [1,2,3] :: Heap Int ghci> minView (coerce h :: Heap (Down Int)) Just 1 w 5IFOXFTQFDJGZUIF3PMF ghci> minView (coerce h :: Heap (Down Int)) error: Couldn't match type ‘Int’ with ‘Down Int’ .VTUCFJust 3! w 8FDBOOPUDPFSDFXJUIPVUUIFJOGPPGOFXUZQFDPOTUSVDUPST
.PSFPO3PMFT w 3PMF5IFUZQFWBSJBCMFIFSFCFIBWFTMJLFUIJT w 5ISFFLJOETrepresentational / nominal / phantom w SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF
.PSFPO3PMFT w 3PMF5IFUZQFWBSJBCMFIFSFCFIBWFTMJLFUIJT w 5ISFFLJOETrepresentational / nominal / phantom w SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF w QIBOUPNVOSFMBUFEUPJUTSFBMDPOUFOUBOZUIJOHHPFT
.PSFPO3PMFT w 3PMF5IFUZQFWBSJBCMFIFSFCFIBWFTMJLFUIJT w 5ISFFLJOETrepresentational / nominal / phantom w SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF w QIBOUPNVOSFMBUFEUPJUTSFBMDPOUFOUBOZUIJOHHPFT w ()$JOGFSTNPTUHFOFSBMSPMFTBUFWFSZUJNF
.PSFPO3PMFT w 3PMF5IFUZQFWBSJBCMFIFSFCFIBWFTMJLFUIJT w 5ISFFLJOETrepresentational / nominal / phantom w SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF w QIBOUPNVOSFMBUFEUPJUTSFBMDPOUFOUBOZUIJOHHPFT w ()$JOGFSTNPTUHFOFSBMSPMFTBUFWFSZUJNF w 4PNFUJNFTMJCSBSZJNQMFNFOUPSNVTUTQFDJGZSPMFT
CFDBVTF ()$DBOUUFMMUIFTFNBOUJDTTQFDJpDUPUIFQBSUJDVMBSUZQF
.PSFPO3PMFT w 3PMF5IFUZQFWBSJBCMFIFSFCFIBWFTMJLFUIJT w 5ISFFLJOETrepresentational / nominal / phantom w SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF w QIBOUPNVOSFMBUFEUPJUTSFBMDPOUFOUBOZUIJOHHPFT w ()$JOGFSTNPTUHFOFSBMSPMFTBUFWFSZUJNF w 4PNFUJNFTMJCSBSZJNQMFNFOUPSNVTUTQFDJGZSPMFT
CFDBVTF ()$DBOUUFMMUIFTFNBOUJDTTQFDJpDUPUIFQBSUJDVMBSUZQF w 8FDBOUDPFSDFUZQFTXJUIPVOFXUZQFDPOTUSVDUPSJOGP
$PFSDJPO3PMFT4VNNBSZ w 8JUIDPFSDFGVODUJPO
XFDBODBTUOFTUUZQFT XJUIUIFTBNFSFQSFTFOUBUJPO
XJUI[FSPDPTU w 8FDBOVTFOFXUZQFTNPSFTBGFMZBOE DPOWFOJFOUMZ w 8FDBODPOUSPMDBTUBCJMJUZCZTQFDJGZJOH3PMFT w 3PMFTBSFVTVBMMZJOGFSSFE w 8FIBWFUPTQFDJGZSPMFTXIFOXFXBOUUP EJTBMMPXDBTUTGPSUIFTFNBOUJDBMSFBTPOT
1SFIJTUPSZPG;FSP$PTU $PFSDJPO(/%DSJTJT w 8FIBWF(FOFSBMJ[FE/FXUZQF%FSJWJOH (/% BULFBTUBMSFBEZJO()$ w "UUIBUUJNF
()$IBEPOMZBUBNFUZQF TZTUFN
FWFSZUIJOHXBTpOF w -BUFS
UZQFGBNJMJFT
("%5TBOETPPODBNF JOUPUIF()$TUZQFTZTUFNBOE w (/%CFDBNFVOPVOE
(/%XBTVOTPVOE newtype Id1 a = MkId1 a newtype Id2 a = MkId2 (Id1 a) deriving (UnsafeCast b) type family Discern a b type instance Discern (Id1 a) b = a type instance Discern (Id2 a) b = b class UnsafeCast to from where unsafe :: from " Discern from to instance UnsafeCast b (Id1 a) where unsafe (MkId1 x) = x unsafeCoerce :: a " b unsafeCoerce x = unsafe (MkId2 (MkId1 x))
(/%XBTVOTPVOE newtype Id1 a = MkId1 a newtype Id2 a = MkId2 (Id1 a) deriving (UnsafeCast b) type family Discern a b type instance Discern (Id1 a) b = a type instance Discern (Id2 a) b = b class UnsafeCast to from where unsafe :: from " Discern from to instance UnsafeCast b (Id1 a) where unsafe (MkId1 x) = x unsafeCoerce :: a " b unsafeCoerce x = unsafe (MkId2 (MkId1 x)) (/%
(/%XBTVOTPVOE newtype Id1 a = MkId1 a newtype Id2 a = MkId2 (Id1 a) deriving (UnsafeCast b) type family Discern a b type instance Discern (Id1 a) b = a type instance Discern (Id2 a) b = b class UnsafeCast to from where unsafe :: from " Discern from to instance UnsafeCast b (Id1 a) where unsafe (MkId1 x) = x unsafeCoerce :: a " b unsafeCoerce x = unsafe (MkId2 (MkId1 x)) (/% $BTUCXBOZUZQFT
(/%JT6OTPVOE newtype Id1 a = MkId1 a newtype Id2 a = MkId2 (Id1 a) deriving (UnsafeCast b) type family Discern a b type instance Discern (Id1 a) b = a type instance Discern (Id2 a) b = b class UnsafeCast to from where unsafe :: from " Discern from to instance UnsafeCast b (Id1 a) where unsafe (MkId1 x) = x unsafeCoerce :: a " b unsafeCoerce x = unsafe (MkId2 (MkId1 x))
(/%JT6OTPVOE newtype Id1 a = MkId1 a newtype Id2 a = MkId2 (Id1 a) deriving (UnsafeCast b) type family Discern a b type instance Discern (Id1 a) b = a type instance Discern (Id2 a) b = b class UnsafeCast to from where unsafe :: from " Discern from to instance UnsafeCast b (Id1 a) where unsafe (MkId1 x) = x unsafeCoerce :: a " b unsafeCoerce x = unsafe (MkId2 (MkId1 x)) (/%CFDBNFUP VTFDPFSDF
(/%JT6OTPVOE newtype Id1 a = MkId1 a newtype Id2 a = MkId2 (Id1 a) deriving (UnsafeCast b) type family Discern a b type instance Discern (Id1 a) b = a type instance Discern (Id2 a) b = b class UnsafeCast to from where unsafe :: from " Discern from to instance UnsafeCast b (Id1 a) where unsafe (MkId1 x) = x unsafeCoerce :: a " b unsafeCoerce x = unsafe (MkId2 (MkId1 x)) (/%CFDBNFUP VTFDPFSDF ()$JTDMFWFS FOPVHIUPJOGFSa BTOPNJOBM
(/%JT6OTPVOE newtype Id1 a = MkId1 a newtype Id2 a = MkId2 (Id1 a) deriving (UnsafeCast b) type family Discern a b type instance Discern (Id1 a) b = a type instance Discern (Id2 a) b = b class UnsafeCast to from where unsafe :: from " Discern from to instance UnsafeCast b (Id1 a) where unsafe (MkId1 x) = x unsafeCoerce :: a " b unsafeCoerce x = unsafe (MkId2 (MkId1 x)) (/%CFDBNFUP VTFDPFSDF ()$JTDMFWFS FOPVHIUPJOGFSa BTOPNJOBM 3FKFDU
&H.POPJETUSVDUVSFPG*E w "TXFIBWFTFFO
8PSEIBWFNVMUJQMFNPOPJEJNQMT {-# LANGUAGE DerivingVia #-} newtype Id = MkId Word deriving (Semigroup, Monoid) via Max Word
&H.POPJETUSVDUVSFPG*E w "TXFIBWFTFFO
8PSEIBWFNVMUJQMFNPOPJEJNQMT w 4VQQPTFXFXBOUUPVTFDIPPTJOHUIFOFXFTU*E .BYJNVN *E BTNPOPJEPQFSBUJPOPO*ET {-# LANGUAGE DerivingVia #-} newtype Id = MkId Word deriving (Semigroup, Monoid) via Max Word
&H.POPJETUSVDUVSFPG*E w "TXFIBWFTFFO
8PSEIBWFNVMUJQMFNPOPJEJNQMT w 4VQQPTFXFXBOUUPVTFDIPPTJOHUIFOFXFTU*E .BYJNVN *E BTNPOPJEPQFSBUJPOPO*ET w Max WordIBTUIFTBNFSFQSBTId
GPSNTBNPOPJEXJUI SFTQFDUUP NBY
{-# LANGUAGE DerivingVia #-} newtype Id = MkId Word deriving (Semigroup, Monoid) via Max Word
&H.POPJETUSVDUVSFPG*E w "TXFIBWFTFFO
8PSEIBWFNVMUJQMFNPOPJEJNQMT w 4VQQPTFXFXBOUUPVTFDIPPTJOHUIFOFXFTU*E .BYJNVN *E BTNPOPJEPQFSBUJPOPO*ET w Max WordIBTUIFTBNFSFQSBTId
GPSNTBNPOPJEXJUI SFTQFDUUP NBY
w %FSJWJOH7JBDBOMJGUUIJTJNQMBVUPNBUJDBMMZUP*E {-# LANGUAGE DerivingVia #-} newtype Id = MkId Word deriving (Semigroup, Monoid) via Max Word
newtype SameRepAs a b = SameRepAs { runSameRepAs :: a } type Iso a b = (Generic a, Generic b, Coercible (Rep a ()) (Rep b ())) instance (Semigroup b, Iso a b) 㱺 Semigroup (SameRepAs a b) where SameRepAs a <> SameRepAs b = ... instance (Monoid b, Iso a b) 㱺 Monoid (SameRepAs a b) where mempty = SameRepAs $ toA mempty where toA :: b -> a toA = to . (coerce :: Rep b () -> Rep a ()) . from
%FSJWJOH7JB4VNNBSZ w "WBJMBCMFTJODF()$ w 8FDBOVTFOFXUZQFTUPTQFDJGZUIFJNQMGPS EFSJWJOHDMBVTFT w $PNCJOFEXJUI(FOFSJDT
XFDBOFWFOEFSJWFUIF JOTUBODFGSPNJTPNPSQIJDUZQF
CVUOPU OFDFTTBSJMZSFQSFTFOUBUJPOBMMZFRVBM
%FSJWJOH7JB4VNNBSZ w "WBJMBCMFTJODF()$ w 8FDBOVTFOFXUZQFTUPTQFDJGZUIFJNQMGPS EFSJWJOHDMBVTFT w $PNCJOFEXJUI(FOFSJDT
XFDBOFWFOEFSJWFUIF JOTUBODFGSPNJTPNPSQIJDUZQF
CVUOPU OFDFTTBSJMZSFQSFTFOUBUJPOBMMZFRVBM w "OZPUIFSJTPNPSQIJTNFYQSFTTJCMFBTBUZQF DPOTUSBJOUJTBMTPBQQMJDBCMFUPUIJTUFDIOJRVF
4VNNBSZ w 5ISFFSPMFTPGOFXUZQFT w *NQMFNFOUBUJPO)JEJOH4IBSJOH4FMFDUJPO w 8JUI%BUB$PFSDF
XFDBODBTUSFQSFTFOUBUJPOBMMZ FRVBMMUZQFTXJUI[FSPDPTU w 5IFOFXUZQF3FWPMVUJPOTUBSUFEIFSF
4VNNBSZ w 5ISFFSPMFTPGOFXUZQFT w *NQMFNFOUBUJPO)JEJOH4IBSJOH4FMFDUJPO w 8JUI%BUB$PFSDF
XFDBODBTUSFQSFTFOUBUJPOBMMZ FRVBMMUZQFTXJUI[FSPDPTU w 5IFOFXUZQF3FWPMVUJPOTUBSUFEIFSF w 8FDBOUSFBUDPNQPVOEUZQFTQSPQFSMZXJUISPMF JOGFSFODFBOEBOOPUBUJPOT
4VNNBSZ w 5ISFFSPMFTPGOFXUZQFT w *NQMFNFOUBUJPO)JEJOH4IBSJOH4FMFDUJPO w 8JUI%BUB$PFSDF
XFDBODBTUSFQSFTFOUBUJPOBMMZ FRVBMMUZQFTXJUI[FSPDPTU w 5IFOFXUZQF3FWPMVUJPOTUBSUFEIFSF w 8FDBOUSFBUDPNQPVOEUZQFTQSPQFSMZXJUISPMF JOGFSFODFBOEBOOPUBUJPOT w 4JODF()$
%FSJWJOH7JBFOBCMFTVTUPVTF OFXUZQFUPDVTUPNJTFUIFEFSJWJOHDMBVTFT
3FGFSFODFT 1. J. Breitner, R. A. Eisenberg, S. P. Jones and S. Weirich, Safe Zero-cost Coercions for Haskell, ICFP 2014. 2. Baldur Blöndal, Andres Löh and Ryan Scott, Deriving Via: How to Turn Hand-Written Instances into an Anti-Pattern, ICFP18.