= MkId Word %JTUJOHVJTIFEBUUZQFMFWFM CVUKVTUBWord internally {-# LANGUAGE GeneralizedNewtypeDeriving #-} newtype Id = MkId Word deriving (Num, Eq) )JEFEBUBDPOTMkId outside the module
= MkId Word %JTUJOHVJTIFEBUUZQFMFWFM CVUKVTUBWord internally {-# LANGUAGE GeneralizedNewtypeDeriving #-} newtype Id = MkId Word deriving (Num, Eq) 6OEFSJWBCMFJO)BTLFMM CVUXFDBOTIBSFWordTJNQM )JEFEBUBDPOTMkId outside the module
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
= MkId Word deriving (Num, Eq) 6OEFSJWBCMFJO)BTLFMM CVUXFDBOTIBSFWordTJNQM &WPMWFT NPSFJO %FSJWJOH7JB module Data.Id (Id ()) where newtype Id = MkId Word )JEFEBUBDPOTMkId outside the module
= 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
• … 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
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
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
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
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 (/%
newtype Option a = Option (Maybe a) instance Semigroup a 㱺 Monoid (Option a) instance Monoid a 㱺 Monoid (Maybe a) instance Semigroup a 㱺 Monoid (Maybe a)
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)
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
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!
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
SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF w QIBOUPNVOSFMBUFEUPJUTSFBMDPOUFOUBOZUIJOHHPFT w ()$JOGFSTNPTUHFOFSBMSPMFTBUFWFSZUJNF
SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF w QIBOUPNVOSFMBUFEUPJUTSFBMDPOUFOUBOZUIJOHHPFT w ()$JOGFSTNPTUHFOFSBMSPMFTBUFWFSZUJNF w 4PNFUJNFTMJCSBSZJNQMFNFOUPSNVTUTQFDJGZSPMFT CFDBVTF ()$DBOUUFMMUIFTFNBOUJDTTQFDJpDUPUIFQBSUJDVMBSUZQF
SFQSFRVJWBMFOUJGUIFZIBWFUIFTBNFSFQSFTFOUBUJPO w OPNJOBMNVTUIBWFFYBDUMZUIFTBNFUZQF w QIBOUPNVOSFMBUFEUPJUTSFBMDPOUFOUBOZUIJOHHPFT w ()$JOGFSTNPTUHFOFSBMSPMFTBUFWFSZUJNF w 4PNFUJNFTMJCSBSZJNQMFNFOUPSNVTUTQFDJGZSPMFT CFDBVTF ()$DBOUUFMMUIFTFNBOUJDTTQFDJpDUPUIFQBSUJDVMBSUZQF w 8FDBOUDPFSDFUZQFTXJUIPVOFXUZQFDPOTUSVDUPSJOGP
= 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))
= 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)) (/%
= 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
= 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))
= 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
= 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
= 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
Max WordIBTUIFTBNFSFQSBTId GPSNTBNPOPJEXJUI SFTQFDUUP NBY {-# LANGUAGE DerivingVia #-} newtype Id = MkId Word deriving (Semigroup, Monoid) via Max Word
Max WordIBTUIFTBNFSFQSBTId GPSNTBNPOPJEXJUI SFTQFDUUP NBY w %FSJWJOH7JBDBOMJGUUIJTJNQMBVUPNBUJDBMMZUP*E {-# LANGUAGE DerivingVia #-} newtype Id = MkId Word deriving (Semigroup, Monoid) via Max Word
:: 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
5IFOFXUZQF3FWPMVUJPOTUBSUFEIFSF w 8FDBOUSFBUDPNQPVOEUZQFTQSPQFSMZXJUISPMF JOGFSFODFBOEBOOPUBUJPOT w 4JODF()$ %FSJWJOH7JBFOBCMFTVTUPVTF OFXUZQFUPDVTUPNJTFUIFEFSJWJOHDMBVTFT
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.