The Great Power of newtypes

The Great Power of newtypes

This is the English translation of my Japanese talk at Five Corp, describing newtypes, Foldables and DerivingVia extensions (https://speakerdeck.com/konn/ben-dang-hasugoi-newtype?slide=167).

717e56bac925ce2db1e6f1cf7708056d?s=128

Hiromi Ishii

August 24, 2018
Tweet

Transcript

  1. 4.
  2. 14.
  3. 17.

    3PMFTPGnewtypeT *NQMFNFOUBUJPO)JEJOH module Data.Id (Id ()) where newtype Id =

    MkId Word %JTUJOHVJTIFEBUUZQFMFWFM  CVUKVTUBWord internally
  4. 18.

    3PMFTPGnewtypeT *NQMFNFOUBUJPO)JEJOH module Data.Id (Id ()) where newtype Id =

    MkId Word %JTUJOHVJTIFEBUUZQFMFWFM  CVUKVTUBWord internally )JEFEBUBDPOTMkId
 outside the module
  5. 19.

    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
  6. 20.

    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
  7. 21.

    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
  8. 22.

    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
  9. 23.

    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
  10. 24.

    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
  11. 30.

    5ZQJDBM"OTXFS 'PMET aggregate :: [ℕ] " (Maybe ℕ, ℕ) aggregate

    = foldr (λ a (m, s) " (Just a `max` m, a + s)) (Nothing, 0) ˞ℕJTTIPSUGPS*OUFHFS
  12. 31.

    5ZQJDBM"OTXFS 'PMET aggregate :: [ℕ] " (Maybe ℕ, ℕ) aggregate

    = foldr (λ a (m, s) " (Just a `max` m, a + s)) (Nothing, 0) 8FIBWFTJNJMBSPQFSBUJPOTPOCPUITJEFT ˞ℕJTTIPSUGPS*OUFHFS
  13. 32.

    5ZQJDBM"OTXFS 'PMET aggregate :: [ℕ] " (Maybe ℕ, ℕ) aggregate

    = foldr (λ a (m, s) " (Just a `max` m, a + s)) (Nothing, 0) 8FIBWFTJNJMBSPQFSBUJPOTPOCPUITJEFT ˞ℕJTTIPSUGPS*OUFHFS
  14. 33.

    5ZQJDBM"OTXFS 'PMET aggregate :: [ℕ] " (Maybe ℕ, ℕ) aggregate

    = foldr (λ a (m, s) " (Just a `max` m, a + s)) (Nothing, 0) 8FIBWFTJNJMBSPQFSBUJPOTPOCPUITJEFT .BQ #JOBSZ 0QFSBUJPO ˞ℕJTTIPSUGPS*OUFHFS
  15. 34.

    5ZQJDBM"OTXFS 'PMET aggregate :: [ℕ] " (Maybe ℕ, ℕ) aggregate

    = foldr (λ a (m, s) " (Just a `max` m, a + s)) (Nothing, 0) 8FIBWFTJNJMBSPQFSBUJPOTPOCPUITJEFT .BQ #JOBSZ 0QFSBUJPO ˞ℕJTTIPSUGPS*OUFHFS
  16. 35.

    5ZQJDBM"OTXFS 'PMET aggregate :: [ℕ] " (Maybe ℕ, ℕ) aggregate

    = foldr (λ a (m, s) " (Just a `max` m, a + s)) (Nothing, 0) 8FIBWFTJNJMBSPQFSBUJPOTPOCPUITJEFT .BQ #JOBSZ 0QFSBUJPO 6OJUT ˞ℕJTTIPSUGPS*OUFHFS
  17. 36.

    5ZQJDBM"OTXFS 'PMET aggregate :: [ℕ] " (Maybe ℕ, ℕ) aggregate

    = foldr (λ a (m, s) " (Just a `max` m, a + s)) (Nothing, 0) 8FIBWFTJNJMBSPQFSBUJPOTPOCPUITJEFT .POPJET .BQ #JOBSZ 0QFSBUJPO 6OJUT ˞ℕJTTIPSUGPS*OUFHFS
  18. 37.

    .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
  19. 39.

    'PMEBCMFDMBTT class Foldable t where foldMap :: Monoid m 㱺

    (a " m) " t a " m … .BQUP.POPJE
  'PMEMFGUUPSJHIU
  20. 40.

    'PMEBCMFDMBTT *UTV⒏DFTUPNBLFNBY  pUJOUIJTGSBNFXPSL class Foldable t where foldMap ::

    Monoid m 㱺 (a " m) " t a " m … .BQUP.POPJE
  'PMEMFGUUPSJHIU
  21. 43.

    &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
  22. 44.

    &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
  23. 45.

    &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
  24. 46.

    &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 (/%
  25. 47.

    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)
  26. 51.

    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)
  27. 52.

    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)
  28. 53.

    'PMEBCMFOFXUZQFWFSTJPO import Control.Arrow aggregate :: [ℕ] " (Maybe ℕ, ℕ)

    aggregate = fmap getMax *** getSum ◦ foldMap (Just . Max &&& Sum)
  29. 54.

    'PMEBCMFOFXUZQFWFSTJPO 4PDPODJTF import Control.Arrow aggregate :: [ℕ] " (Maybe ℕ,

    ℕ) aggregate = fmap getMax *** getSum ◦ foldMap (Just . Max &&& Sum)
  30. 56.

    'PMEBCMFOFXUZQFWFSTJPO 4PDPODJTF *UTTUJMMUFEJPVTUPVOXSBQ.BYBOE4VNUIFZ TJUTJOOFTUFEUZQFT import Control.Arrow aggregate :: [ℕ] "

    (Maybe ℕ, ℕ) aggregate = fmap getMax *** getSum ◦ foldMap (Just . Max &&& Sum) ‎;FSP$PTU$PFSDJPOT
  31. 58.
  32. 65.

    #VU

  33. 72.

    ;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
  34. 73.

    8JUIDPFSDF import Control.Arrow aggregate :: [ℕ] " (Maybe ℕ, ℕ)

    aggregate = fmap getMax *** getSum ◦ foldMap (Just . Max &&& Sum)
  35. 74.

    8FHFUJU import Control.Arrow import Data.Coerce aggregate :: [ℕ] " (Maybe

    ℕ, ℕ) aggregate = coerce ◦ foldMap (Just . Max &&& Sum)
  36. 75.

    8FHFUJU import Control.Arrow import Data.Coerce aggregate :: [ℕ] " (Maybe

    ℕ, ℕ) aggregate = coerce ◦ foldMap (Just . Max &&& Sum) $BTUJOH OFTUFE UZQFTXJUI[FSP DPTU
  37. 76.

    8FHFUJU import Control.Arrow import Data.Coerce aggregate :: [ℕ] " (Maybe

    ℕ, ℕ) aggregate = coerce ◦ foldMap (Just . Max &&& Sum) coerce :: (Maybe (Max ), Sum ) → (Maybe , ) $BTUJOH OFTUFE UZQFTXJUI[FSP DPTU
  38. 77.

    8FHFUJU import Control.Arrow import Data.Coerce aggregate :: [ℕ] " (Maybe

    ℕ, ℕ) aggregate = coerce ◦ foldMap (Just . Max &&& Sum) w /PF⒎FDUPOUIFPGTDBOOJOHTJODFJUT[FSPDPTU coerce :: (Maybe (Max ), Sum ) → (Maybe , ) $BTUJOH OFTUFE UZQFTXJUI[FSP DPTU
  39. 78.

    8FHFUJU import Control.Arrow import Data.Coerce aggregate :: [ℕ] " (Maybe

    ℕ, ℕ) aggregate = coerce ◦ foldMap (Just . Max &&& Sum) w /PF⒎FDUPOUIFPGTDBOOJOHTJODFJUT[FSPDPTU w +VTUPOFDBMMGPSDPFSDFUPNBLFJUEPOF coerce :: (Maybe (Max ), Sum ) → (Maybe , ) $BTUJOH OFTUFE UZQFTXJUI[FSP DPTU
  40. 82.

    $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
  41. 83.

    $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
  42. 84.

    $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
  43. 85.

    $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 
  44. 86.

    $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 
  45. 87.
  46. 89.

    3PMFT w 8FDBODBTUUIFNXJUIDPFSDF ghci> h = fromList [1,2,3] :: Heap

    Int ghci> minView (coerce h :: Heap (Down Int)) Just 1
  47. 90.

    3PMFT w 8FDBODBTUUIFNXJUIDPFSDF ghci> h = fromList [1,2,3] :: Heap

    Int ghci> minView (coerce h :: Heap (Down Int)) Just 1 .VTUCFJust 3!
  48. 91.

    3PMFT w 8FDBODBTUUIFNXJUIDPFSDF ghci> h = fromList [1,2,3] :: Heap

    Int ghci> minView (coerce h :: Heap (Down Int)) Just 1 w 5IFOXFTQFDJGZUIF3PMF .VTUCFJust 3!
  49. 92.

    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!
  50. 93.

    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!
  51. 94.

    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
  52. 99.

    .PSFPO3PMFT w 3PMF5IFUZQFWBSJBCMFIFSFCFIBWFTMJLFUIJT w 5ISFFLJOETrepresentational / nominal / phantom w

    SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF
  53. 100.

    .PSFPO3PMFT w 3PMF5IFUZQFWBSJBCMFIFSFCFIBWFTMJLFUIJT w 5ISFFLJOETrepresentational / nominal / phantom w

    SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF w QIBOUPNVOSFMBUFEUPJUTSFBMDPOUFOUBOZUIJOHHPFT
  54. 101.

    .PSFPO3PMFT w 3PMF5IFUZQFWBSJBCMFIFSFCFIBWFTMJLFUIJT w 5ISFFLJOETrepresentational / nominal / phantom w

    SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF w QIBOUPNVOSFMBUFEUPJUTSFBMDPOUFOUBOZUIJOHHPFT w ()$JOGFSTNPTUHFOFSBMSPMFTBUFWFSZUJNF
  55. 102.

    .PSFPO3PMFT w 3PMF5IFUZQFWBSJBCMFIFSFCFIBWFTMJLFUIJT w 5ISFFLJOETrepresentational / nominal / phantom w

    SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF w QIBOUPNVOSFMBUFEUPJUTSFBMDPOUFOUBOZUIJOHHPFT w ()$JOGFSTNPTUHFOFSBMSPMFTBUFWFSZUJNF w 4PNFUJNFTMJCSBSZJNQMFNFOUPSNVTUTQFDJGZSPMFT CFDBVTF ()$DBOUUFMMUIFTFNBOUJDTTQFDJpDUPUIFQBSUJDVMBSUZQF
  56. 103.

    .PSFPO3PMFT w 3PMF5IFUZQFWBSJBCMFIFSFCFIBWFTMJLFUIJT w 5ISFFLJOETrepresentational / nominal / phantom w

    SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF w QIBOUPNVOSFMBUFEUPJUTSFBMDPOUFOUBOZUIJOHHPFT w ()$JOGFSTNPTUHFOFSBMSPMFTBUFWFSZUJNF w 4PNFUJNFTMJCSBSZJNQMFNFOUPSNVTUTQFDJGZSPMFT CFDBVTF ()$DBOUUFMMUIFTFNBOUJDTTQFDJpDUPUIFQBSUJDVMBSUZQF w 8FDBOUDPFSDFUZQFTXJUIPVOFXUZQFDPOTUSVDUPSJOGP
  57. 104.

    $PFSDJPO3PMFT4VNNBSZ w 8JUIDPFSDFGVODUJPO XFDBODBTUOFTUUZQFT XJUIUIFTBNFSFQSFTFOUBUJPO XJUI[FSPDPTU w 8FDBOVTFOFXUZQFTNPSFTBGFMZBOE DPOWFOJFOUMZ w

    8FDBODPOUSPMDBTUBCJMJUZCZTQFDJGZJOH3PMFT w 3PMFTBSFVTVBMMZJOGFSSFE w 8FIBWFUPTQFDJGZSPMFTXIFOXFXBOUUP EJTBMMPXDBTUTGPSUIFTFNBOUJDBMSFBTPOT
  58. 107.

    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
  59. 108.

    (/%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))
  60. 109.

    (/%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)) (/%
  61. 110.

    (/%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
  62. 114.

    (/%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))
  63. 115.

    (/%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
  64. 116.

    (/%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
  65. 117.

    (/%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
  66. 118.

  67. 135.

    &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
  68. 136.

    &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
  69. 145.

    $PNQMJDBUFE&YBNQMF w 4QFDJpFTUIFFODPEJOHNFUIPEBUUZQFMFWFM w 4UBUJDBMMZBTTVSFTUIBUTBNFFODPEJOHJTVTFEJO'SPN+40/5P+40/ data OtherConfig = OtherConfig {

    otrNameOfProcess :: Maybe String , otrArgsToProcess :: [String] } deriving (Read, Show, Eq, Ord, Generic) deriving (ToJSON, FromJSON) via WithOptions '[ FieldLabelModifier '[CamelTo2 "-"] , ConstructorTagModifier '[CamelTo2 "-"] , OmitNothingFields 'True ] OtherConfig
  70. 146.

    &YBNQMFPG*TP data Blog = Blog { authors :: [Author] ,

    articles :: [Article] } deriving (Generic) deriving (Semigroup, Monoid) via Blog `SameRepAs` ([Author], Dual [Article]) {- ghci> mconcat [Blog ["1"] ["1"], Blog ["2"] ["3","4"]] Blog {authors = ["1","2"], articles = ["3","4","1"]} -}
  71. 147.

    &YBNQMFPG*TP DPOU 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
  72. 152.

    %FSJWJOH7JB4VNNBSZ w "WBJMBCMFTJODF()$ w 8FDBOVTFOFXUZQFTUPTQFDJGZUIFJNQMGPS EFSJWJOHDMBVTFT w $PNCJOFEXJUI(FOFSJDT XFDBOFWFOEFSJWFUIF JOTUBODFGSPNJTPNPSQIJDUZQF

    CVUOPU OFDFTTBSJMZSFQSFTFOUBUJPOBMMZFRVBM w "OZPUIFSJTPNPSQIJTNFYQSFTTJCMFBTBUZQF DPOTUSBJOUJTBMTPBQQMJDBCMFUPUIJTUFDIOJRVF
  73. 153.
  74. 154.
  75. 159.

    4VNNBSZ w 5ISFFSPMFTPGOFXUZQFT w *NQMFNFOUBUJPO)JEJOH4IBSJOH4FMFDUJPO w 8JUI%BUB$PFSDF XFDBODBTUSFQSFTFOUBUJPOBMMZ FRVBMMUZQFTXJUI[FSPDPTU w

    5IFOFXUZQF3FWPMVUJPOTUBSUFEIFSF w 8FDBOUSFBUDPNQPVOEUZQFTQSPQFSMZXJUISPMF JOGFSFODFBOEBOOPUBUJPOT
  76. 160.

    4VNNBSZ w 5ISFFSPMFTPGOFXUZQFT w *NQMFNFOUBUJPO)JEJOH4IBSJOH4FMFDUJPO w 8JUI%BUB$PFSDF XFDBODBTUSFQSFTFOUBUJPOBMMZ FRVBMMUZQFTXJUI[FSPDPTU w

    5IFOFXUZQF3FWPMVUJPOTUBSUFEIFSF w 8FDBOUSFBUDPNQPVOEUZQFTQSPQFSMZXJUISPMF JOGFSFODFBOEBOOPUBUJPOT w 4JODF()$ %FSJWJOH7JBFOBCMFTVTUPVTF OFXUZQFUPDVTUPNJTFUIFEFSJWJOHDMBVTFT
  77. 161.

    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.