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. 5IF(SFBU1PXFSPG newtypeT !NS@LPOO IUUQTLPOOTBODPN 4MJEFTBSFBWBJMBCMFBUhttp://bit.ly/derivia
 &YBNQMFDPEFTBSFPO(JU)VCkonn/newtype-talk-five

  2. 4FMG*OUSPEVDUJPO w )JSPNJ*4)**ʢ!NS@LPOOʣ w %PDUPSBM$BOEJEBUFJO.BUIFNBUJDT w 3FTFBSDI"SFB.BUIFNBUJDBM-PHJD  $PNQVUFS4DJFODF w

    8SJUJOHBOEUFBDIJOH)BTLFMMGPSZFBST
  3. 5IF(SFBU1PXFSPGnewtypeT 3PMFT 4BGF[FSPDPTUDPFSDJPOT BOE%FSJWJOH7JB ʙ.POPJE&'PMEBCMFJODMVEFEʙ (SFBU

  4. newtype

  5. newtype newtype Foo α = Bar α newtype Id =

    MkId Word
  6. newtype w "UZQFXJUIBTJOHMFDPOTUSVDUPSBOEpFME newtype Foo α = Bar α newtype

    Id = MkId Word
  7. newtype w "UZQFXJUIBTJOHMFDPOTUSVDUPSBOEpFME w )BTUIF4BNFSFQSFTFOUBUJPOBTJUTPOMZpFME newtype Foo α = Bar

    α newtype Id = MkId Word
  8. newtype w "UZQFXJUIBTJOHMFDPOTUSVDUPSBOEpFME w )BTUIF4BNFSFQSFTFOUBUJPOBTJUTPOMZpFME w %JTUJOHVJTIFEGSPNUIFPSJHJOBMUZQFBUUZQF MFWFM CVUIBTUIFTBNFNFNPSZSFQSFTFOUBUJPO BTUIFPSJHJOBM

    BOEFWBMVBUFETUSJDUMZ newtype Foo α = Bar α newtype Id = MkId Word
  9. 5ZQJDBM/FXCJF2VFTUJPO

  10. 5ZQJDBM/FXCJF2VFTUJPO 8IBUJTUIFEJ⒎FSFODFGSPNdata?"

  11. 5ZQJDBM/FXCJF2VFTUJPO 8IBUJTUIFEJ⒎FSFODFGSPNdata?" *UTF⒏DJFOUUIBOLTUPJUTSFQSFTFOUBUJPO

  12. 5ZQJDBM/FXCJF2VFTUJPO 8IBUJTUIFEJ⒎FSFODFGSPNdata?" *UTF⒏DJFOUUIBOLTUPJUTSFQSFTFOUBUJPO *UEPFTOUNBUUFSNVDIUPNF*ESBUIFS
 VTFdata

  13. 5ZQJDBM/FXCJF2VFTUJPO 8IBUJTUIFEJ⒎FSFODFGSPNdata?" *UTF⒏DJFOUUIBOLTUPJUTSFQSFTFOUBUJPO *UEPFTOUNBUUFSNVDIUPNF*ESBUIFS
 VTFdata 8FMM XFIBWFfunpack-strict-fieldsBOZIPX

  14. 3FBMMZ

  15. 3PMFTPGnewtypeT

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

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

    MkId Word %JTUJOHVJTIFEBUUZQFMFWFM  CVUKVTUBWord internally
  18. 3PMFTPGnewtypeT *NQMFNFOUBUJPO)JEJOH module Data.Id (Id ()) where newtype Id =

    MkId Word %JTUJOHVJTIFEBUUZQFMFWFM  CVUKVTUBWord internally )JEFEBUBDPOTMkId
 outside the module
  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
  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
  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
  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
  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
  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
  25. *NQMFNFOUBUJPO 4FMFDUJPO

  26. *NQMFNFOUBUJPO 4FMFDUJPO .POPJE'PMEBCMFBT&YBNQMFT

  27. &YFSDJTF-JTU4DBOOJOH 2 (JWFOBMJTUPGJOUFHFST DBMDVMBUFTJUTNBYJNVN BOEUPUBMTVNCZTDBOOJOHMJTUFYBDUMZPODF ˞%POPUVTFfoldlPSfoldsQBDLBHFT

  28. 5ZQJDBM"OTXFS

  29. 5ZQJDBM"OTXFS 'PMET

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

    = foldr (λ a (m, s) " (Just a `max` m, a + s)) (Nothing, 0) ˞ℕJTTIPSUGPS*OUFHFS
  31. 5ZQJDBM"OTXFS 'PMET aggregate :: [ℕ] " (Maybe ℕ, ℕ) aggregate

    = foldr (λ a (m, s) " (Just a `max` m, a + s)) (Nothing, 0) 8FIBWFTJNJMBSPQFSBUJPOTPOCPUITJEFT ˞ℕJTTIPSUGPS*OUFHFS
  32. 5ZQJDBM"OTXFS 'PMET aggregate :: [ℕ] " (Maybe ℕ, ℕ) aggregate

    = foldr (λ a (m, s) " (Just a `max` m, a + s)) (Nothing, 0) 8FIBWFTJNJMBSPQFSBUJPOTPOCPUITJEFT ˞ℕJTTIPSUGPS*OUFHFS
  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
  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
  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
  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
  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
  38. 'PMEBCMFDMBTT class Foldable t where foldMap :: Monoid m 㱺

    (a " m) " t a " m …
  39. 'PMEBCMFDMBTT class Foldable t where foldMap :: Monoid m 㱺

    (a " m) " t a " m … .BQUP.POPJE
  'PMEMFGUUPSJHIU
  40. 'PMEBCMFDMBTT *UTV⒏DFTUPNBLFNBY  pUJOUIJTGSBNFXPSL class Foldable t where foldMap ::

    Monoid m 㱺 (a " m) " t a " m … .BQUP.POPJE
  'PMEMFGUUPSJHIU
  41. 'PMEBCMFDMBTT *UTV⒏DFTUPNBLFNBY  pUJOUIJTGSBNFXPSL 8FDBOIBWFBUNPTUPOFJOTUBODFGPSMonoid Word class Foldable t where

    foldMap :: Monoid m 㱺 (a " m) " t a " m … .BQUP.POPJE
  'PMEMFGUUPSJHIU
  42. 'PMEBCMFDMBTT *UTV⒏DFTUPNBLFNBY  pUJOUIJTGSBNFXPSL 8FDBOIBWFBUNPTUPOFJOTUBODFGPSMonoid Word *NQMFNFOUBUJPO4FMFDUJPOVTJOHnewtypeT class Foldable t

    where foldMap :: Monoid m 㱺 (a " m) " t a " m … .BQUP.POPJE
  'PMEMFGUUPSJHIU
  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
  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
  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
  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 (/%
  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)
  48. 1SBDUJDBM3FNBSL newtype Option a = Option (Maybe a) instance Semigroup

    a 㱺 Monoid (Option a)
  49. 1SBDUJDBM3FNBSL OptionBEKPJOTVOJU UVSOJOHTFNJHSPVQTJOUPNPOPJET newtype Option a = Option (Maybe a)

    instance Semigroup a 㱺 Monoid (Option a)
  50. 1SBDUJDBM3FNBSL OptionBEKPJOTVOJU UVSOJOHTFNJHSPVQTJOUPNPOPJET ʙ()$ɿ.BZCFSFRVJSFT.POPJEBBTBDPOTUSBJOU newtype Option a = Option (Maybe

    a) instance Semigroup a 㱺 Monoid (Option a) instance Monoid a 㱺 Monoid (Maybe a)
  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)
  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)
  53. 'PMEBCMFOFXUZQFWFSTJPO import Control.Arrow aggregate :: [ℕ] " (Maybe ℕ, ℕ)

    aggregate = fmap getMax *** getSum ◦ foldMap (Just . Max &&& Sum)
  54. 'PMEBCMFOFXUZQFWFSTJPO 4PDPODJTF import Control.Arrow aggregate :: [ℕ] " (Maybe ℕ,

    ℕ) aggregate = fmap getMax *** getSum ◦ foldMap (Just . Max &&& Sum)
  55. 'PMEBCMFOFXUZQFWFSTJPO 4PDPODJTF *UTTUJMMUFEJPVTUPVOXSBQ.BYBOE4VNUIFZ TJUTJOOFTUFEUZQFT import Control.Arrow aggregate :: [ℕ] "

    (Maybe ℕ, ℕ) aggregate = fmap getMax *** getSum ◦ foldMap (Just . Max &&& Sum)
  56. 'PMEBCMFOFXUZQFWFSTJPO 4PDPODJTF *UTTUJMMUFEJPVTUPVOXSBQ.BYBOE4VNUIFZ TJUTJOOFTUFEUZQFT import Control.Arrow aggregate :: [ℕ] "

    (Maybe ℕ, ℕ) aggregate = fmap getMax *** getSum ◦ foldMap (Just . Max &&& Sum) ‎;FSP$PTU$PFSDJPOT
  57. 4BGF;FSP$PTU $PFSDJPOTBOE3PMFT

  58. 4BGF;FSP$PTU $PFSDJPOTBOE3PMFT [1] Breitner, Eisenberg, Peyton Jones and Weirich, 2014

    "HSFBUJOWFOUJPO
 PQFOJOHVQUIFOFXFSBPGOFXUZQFT
  59. #FGPSF )BTLFMMFSTDPNQMBJOU

  60. *OEFFE OFXUZQFTBSF DPOWJOFOUGPSJNQM TFMFDUJPO

  61. #VUXFIBWFUPVOXSBQ UIFNPOFCZPOF

  62. %PJOHTPJTOPUTP F⒏DJFOU

  63. 4JODFXFLOPXJUTTBGF  XFDBOVTF VOTBGF$PFSDF

  64. *UTOPURVJUFTNBSU

  65. #VU

  66. *O 
 5IF3FWPMVUJPOUPPLQMBDF UPOFXUZQFT

  67. ;FSP$PTU$PFSDJPO

  68. ;FSP$PTU$PFSDJPO import Data.Coerce (coerce) coerce :: Coercible a b 㱺

    a " b
  69. ;FSP$PTU$PFSDJPO w $PFSDJCMFSFMBUFTUXPUZQFTXJUIUIFTBNFNFNPSZSFQS import Data.Coerce (coerce) coerce :: Coercible a

    b 㱺 a " b
  70. ;FSP$PTU$PFSDJPO w $PFSDJCMFSFMBUFTUXPUZQFTXJUIUIFTBNFNFNPSZSFQS w *UTFFNTMJLFBUZQFDMBTT CVU()$HFOFSBUFTBOJOGPSNBUJPO BUDPNQJMFUJNF BOEVTFSDBOOPUBEEDVTUPNJOTUBODF import Data.Coerce

    (coerce) coerce :: Coercible a b 㱺 a " b
  71. ;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
  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
  73. 8JUIDPFSDF import Control.Arrow aggregate :: [ℕ] " (Maybe ℕ, ℕ)

    aggregate = fmap getMax *** getSum ◦ foldMap (Just . Max &&& Sum)
  74. 8FHFUJU import Control.Arrow import Data.Coerce aggregate :: [ℕ] " (Maybe

    ℕ, ℕ) aggregate = coerce ◦ foldMap (Just . Max &&& Sum)
  75. 8FHFUJU import Control.Arrow import Data.Coerce aggregate :: [ℕ] " (Maybe

    ℕ, ℕ) aggregate = coerce ◦ foldMap (Just . Max &&& Sum) $BTUJOH OFTUFE UZQFTXJUI[FSP DPTU
  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
  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
  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
  79. $BTUJOHCXOFTUFEUZQFT

  80. $BTUJOHCXOFTUFEUZQFT *UTDPOWFOJFOUUIBUXFDBODBTUBOZOFTUFEUZQFT

  81. $BTUJOHCXOFTUFEUZQFT *UTDPOWFOJFOUUIBUXFDBODBTUBOZOFTUFEUZQFT 3FBMMZ

  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
  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
  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
  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 
  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 
  87. 3PMFT

  88. 3PMFT w 8FDBODBTUUIFNXJUIDPFSDF

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

    Int ghci> minView (coerce h :: Heap (Down Int)) Just 1
  90. 3PMFT w 8FDBODBTUUIFNXJUIDPFSDF ghci> h = fromList [1,2,3] :: Heap

    Int ghci> minView (coerce h :: Heap (Down Int)) Just 1 .VTUCFJust 3!
  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!
  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!
  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!
  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
  95. .PSFPO3PMFT

  96. .PSFPO3PMFT w 3PMF5IFUZQFWBSJBCMFIFSFCFIBWFTMJLFUIJT

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

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

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

    SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF
  100. .PSFPO3PMFT w 3PMF5IFUZQFWBSJBCMFIFSFCFIBWFTMJLFUIJT w 5ISFFLJOETrepresentational / nominal / phantom w

    SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF w QIBOUPNVOSFMBUFEUPJUTSFBMDPOUFOUBOZUIJOHHPFT
  101. .PSFPO3PMFT w 3PMF5IFUZQFWBSJBCMFIFSFCFIBWFTMJLFUIJT w 5ISFFLJOETrepresentational / nominal / phantom w

    SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF w QIBOUPNVOSFMBUFEUPJUTSFBMDPOUFOUBOZUIJOHHPFT w ()$JOGFSTNPTUHFOFSBMSPMFTBUFWFSZUJNF
  102. .PSFPO3PMFT w 3PMF5IFUZQFWBSJBCMFIFSFCFIBWFTMJLFUIJT w 5ISFFLJOETrepresentational / nominal / phantom w

    SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF w QIBOUPNVOSFMBUFEUPJUTSFBMDPOUFOUBOZUIJOHHPFT w ()$JOGFSTNPTUHFOFSBMSPMFTBUFWFSZUJNF w 4PNFUJNFTMJCSBSZJNQMFNFOUPSNVTUTQFDJGZSPMFT CFDBVTF ()$DBOUUFMMUIFTFNBOUJDTTQFDJpDUPUIFQBSUJDVMBSUZQF
  103. .PSFPO3PMFT w 3PMF5IFUZQFWBSJBCMFIFSFCFIBWFTMJLFUIJT w 5ISFFLJOETrepresentational / nominal / phantom w

    SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF w QIBOUPNVOSFMBUFEUPJUTSFBMDPOUFOUBOZUIJOHHPFT w ()$JOGFSTNPTUHFOFSBMSPMFTBUFWFSZUJNF w 4PNFUJNFTMJCSBSZJNQMFNFOUPSNVTUTQFDJGZSPMFT CFDBVTF ()$DBOUUFMMUIFTFNBOUJDTTQFDJpDUPUIFQBSUJDVMBSUZQF w 8FDBOUDPFSDFUZQFTXJUIPVOFXUZQFDPOTUSVDUPSJOGP
  104. $PFSDJPO3PMFT4VNNBSZ w 8JUIDPFSDFGVODUJPO XFDBODBTUOFTUUZQFT XJUIUIFTBNFSFQSFTFOUBUJPO XJUI[FSPDPTU w 8FDBOVTFOFXUZQFTNPSFTBGFMZBOE DPOWFOJFOUMZ w

    8FDBODPOUSPMDBTUBCJMJUZCZTQFDJGZJOH3PMFT w 3PMFTBSFVTVBMMZJOGFSSFE w 8FIBWFUPTQFDJGZSPMFTXIFOXFXBOUUP EJTBMMPXDBTUTGPSUIFTFNBOUJDBMSFBTPOT
  105. :FT 5IBUTXIBUXF XBOUFE

  106. 8IZXFEJEOUIBWF UIJT

  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
  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))
  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)) (/%
  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
  111. 5IBUTUFSSJCMF

  112. 8FIBWFUPTBWFUIF (/%

  113. 5IBUTXIZ3PMFT BSFFNFSHFE

  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))
  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
  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
  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
  118. /PX OFXUZQFTDBO QMBZUIFJSSPMFT
 UIBOLTUP3PMFT

  119. 3PMFTPGOFXUZQFT

  120. *NQMFNFOUBUJPO
 )JEJOH

  121. *NQMFNFOUBUJPO
 4IBSJOH

  122. *NQMFNFOUBUJPO
 4FMFDUJPO

  123. 5IJTJTXIFSF
 OFXUZQFT TUBOETOPX

  124. 'SPNOPXPO 5IFGVUVSFPG OFXUZQF

  125. 5IFGVUVSFPGOFXUZQFT  PS%FSJWJOH7JB

  126. 5IFGVUVSFPGOFXUZQFT  PS%FSJWJOH7JB d8IFOUIFJNQMTIBSJOHBOETFMFDUJPONFFUd [2] Blöndal, Löh and Scott, 2018

  127. %FSJWJOH7JB.PSF'MFYJCMF *NQMFNFOUBUJPO4IBSJOH

  128. %FSJWJOH7JB.PSF'MFYJCMF *NQMFNFOUBUJPO4IBSJOH w "OFXGFBUVSFPG()$

  129. %FSJWJOH7JB.PSF'MFYJCMF *NQMFNFOUBUJPO4IBSJOH w "OFXGFBUVSFPG()$ w ()$BMQIBJTSFMFBTFEBUUIFUJNF PGUIJTUBML

  130. %FSJWJOH7JB.PSF'MFYJCMF *NQMFNFOUBUJPO4IBSJOH w "OFXGFBUVSFPG()$ w ()$BMQIBJTSFMFBTFEBUUIFUJNF PGUIJTUBML w 8FDBOVTFOFXUZQFTBTBIJOUGPSEFSJWJOH DMBVTFT

  131. &H.POPJETUSVDUVSFPG*E {-# LANGUAGE DerivingVia #-} newtype Id = MkId Word

    deriving (Semigroup, Monoid) via Max Word
  132. &H.POPJETUSVDUVSFPG*E w "TXFIBWFTFFO 8PSEIBWFNVMUJQMFNPOPJEJNQMT {-# LANGUAGE DerivingVia #-} newtype Id

    = MkId Word deriving (Semigroup, Monoid) via Max Word
  133. &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
  134. &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
  135. &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
  136. %FSJWJOH7JBWT(/%

  137. %FSJWJOH7JBWT(/% w %FSJWJOH7JBJTBTVQFSTFUPG(/%

  138. %FSJWJOH7JBWT(/% w %FSJWJOH7JBJTBTVQFSTFUPG(/% w (/%KVTUMPPLTBUUIFJOOFSNPTUUZQF

  139. %FSJWJOH7JBWT(/% w %FSJWJOH7JBJTBTVQFSTFUPG(/% w (/%KVTUMPPLTBUUIFJOOFSNPTUUZQF w %FSJWJOH7JBMFUVTSFVTFUIFJNQMPGBOZ $PFSDJCMFUZQFT XJUIPVUBOZDPTU

  140. %FSJWJOH7JBJTOPUMJNJUFEUP OFXUZQFT

  141. %FSJWJOH7JBJTOPUMJNJUFEUP OFXUZQFT w *OUIFPSJHJOBMQBQFS JUJTQSPQPTFEUPVTF %FSJWJOH7JBUPTIBSFJNQMFNFOUBUJPOT CFUXFFOBOZJTPNPQIJDUZQFT ˞5IJTJTPNPSQIJDNFBOTTMJHIUMZTUSPOHFSDPOEJUJPO
 ɹJUNFBOTUIFJSHFOFSJDSFQSFTFOUBUJPOJTUIFTBNF

  142. %FSJWJOH7JBJTOPUMJNJUFEUP OFXUZQFT w *OUIFPSJHJOBMQBQFS JUJTQSPQPTFEUPVTF %FSJWJOH7JBUPTIBSFJNQMFNFOUBUJPOT CFUXFFOBOZJTPNPQIJDUZQFT $PNCJOBUJPOPG(FOFSJDTBOE$PFSDJPO ˞5IJTJTPNPSQIJDNFBOTTMJHIUMZTUSPOHFSDPOEJUJPO
 ɹJUNFBOTUIFJSHFOFSJDSFQSFTFOUBUJPOJTUIFTBNF

  143. %FNP 4UBUJDEFpOJUJPOPG+40/EFTFSJBMJ[BUJPOJOTUBODF *NQMTIBSJOHCXJTPNPSQIJDUZQFT ˞$PNQMFUFDPEFJTBWBJMBCMFBUhttp://bit.ly/derivia

  144. $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
  145. &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"]} -}
  146. &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
  147. %FSJWJOH7JB4VNNBSZ

  148. %FSJWJOH7JB4VNNBSZ w "WBJMBCMFTJODF()$

  149. %FSJWJOH7JB4VNNBSZ w "WBJMBCMFTJODF()$ w 8FDBOVTFOFXUZQFTUPTQFDJGZUIFJNQMGPS EFSJWJOHDMBVTFT

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

    CVUOPU OFDFTTBSJMZSFQSFTFOUBUJPOBMMZFRVBM
  151. %FSJWJOH7JB4VNNBSZ w "WBJMBCMFTJODF()$ w 8FDBOVTFOFXUZQFTUPTQFDJGZUIFJNQMGPS EFSJWJOHDMBVTFT w $PNCJOFEXJUI(FOFSJDT XFDBOFWFOEFSJWFUIF JOTUBODFGSPNJTPNPSQIJDUZQF

    CVUOPU OFDFTTBSJMZSFQSFTFOUBUJPOBMMZFRVBM w "OZPUIFSJTPNPSQIJTNFYQSFTTJCMFBTBUZQF DPOTUSBJOUJTBMTPBQQMJDBCMFUPUIJTUFDIOJRVF
  152. 4VNNBSZ

  153. 4VNNBSZ

  154. 4VNNBSZ w 5ISFFSPMFTPGOFXUZQFT

  155. 4VNNBSZ w 5ISFFSPMFTPGOFXUZQFT w *NQMFNFOUBUJPO)JEJOH4IBSJOH4FMFDUJPO

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

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

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

    5IFOFXUZQF3FWPMVUJPOTUBSUFEIFSF w 8FDBOUSFBUDPNQPVOEUZQFTQSPQFSMZXJUISPMF JOGFSFODFBOEBOOPUBUJPOT
  159. 4VNNBSZ w 5ISFFSPMFTPGOFXUZQFT w *NQMFNFOUBUJPO)JEJOH4IBSJOH4FMFDUJPO w 8JUI%BUB$PFSDF XFDBODBTUSFQSFTFOUBUJPOBMMZ FRVBMMUZQFTXJUI[FSPDPTU w

    5IFOFXUZQF3FWPMVUJPOTUBSUFEIFSF w 8FDBOUSFBUDPNQPVOEUZQFTQSPQFSMZXJUISPMF JOGFSFODFBOEBOOPUBUJPOT w 4JODF()$ %FSJWJOH7JBFOBCMFTVTUPVTF OFXUZQFUPDVTUPNJTFUIFEFSJWJOHDMBVTFT
  160. 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.