Currently Dupable typeclass requires implementing the dupV function:
class Consumable a => Dupable a where
dupV :: KnownNat n => a #-> V n a
However, to me, it's not obvious how that can be implemented; and after spending hours on it today I couldn't figure it out. However
dup2 :: Dupable a => a #-> (a, a)
function is simpler to implement, and I think we should define Dupable in terms of this. Dupable's laws are already defined in terms of dup2 instead of dupV, which also points to dup2 being the simpler option.
I had this issue when trying to implement a Dupable instance for Data.Array.Mutable.Linear. The existing Dupable implementations all have simple implementations implemented using V's applicative instance (or using other Dupable instances), but we can not use that if we can not share the value. In Array's case, it's easy to implement a function like clone :: Array a #-> (Array a, Array a), but going from that to dupV was not easy (for me).
We should still keep dupV in the class and define {-# MINIMAL dup2 | dupV #-}, in case when dupV is more efficient.
Currently
Dupabletypeclass requires implementing thedupVfunction:However, to me, it's not obvious how that can be implemented; and after spending hours on it today I couldn't figure it out. However
function is simpler to implement, and I think we should define
Dupablein terms of this.Dupable's laws are already defined in terms ofdup2instead ofdupV, which also points todup2being the simpler option.I had this issue when trying to implement a
Dupableinstance forData.Array.Mutable.Linear. The existingDupableimplementations all have simple implementations implemented usingV's applicative instance (or using otherDupableinstances), but we can not use that if we can not share the value. InArray's case, it's easy to implement a function likeclone :: Array a #-> (Array a, Array a), but going from that todupVwas not easy (for me).We should still keep
dupVin the class and define{-# MINIMAL dup2 | dupV #-}, in case whendupVis more efficient.