Skip to content

Instantly share code, notes, and snippets.

@ramirez7
Last active May 8, 2024 20:27
Show Gist options
  • Save ramirez7/5b6ff532b7b377801d17f2bb8d20b7df to your computer and use it in GitHub Desktop.
Save ramirez7/5b6ff532b7b377801d17f2bb8d20b7df to your computer and use it in GitHub Desktop.
-- Similar to this old gist https://gist.github.com/ramirez7/11167d5f1c2a1153c3fb20643f4cb2d4
--
-- Scala is a bit more general though thanks to its path-dependent types
module SetBy
( SetBy
) where
import Data.Map (Map)
import qualified Data.Map as Map
import GHC.TypeLits
import GHC.Records
import Data.Kind
data SetBy (f :: Symbol) b a where
MkSetBy :: (HasField f a b, Ord b) => Map b a -> SetBy f b a
empty :: HasField f a b => Ord b => SetBy f b a
empty = MkSetBy mempty
singleton :: forall f a b. HasField f a b => Ord b => a -> SetBy f b a
singleton v = MkSetBy $ Map.singleton (getField @f v) v
insert :: forall f a b. a -> SetBy f b a -> SetBy f b a
insert v (MkSetBy m) = MkSetBy $ Map.insert (getField @f v) v m
instance Semigroup (SetBy f a b) where
MkSetBy x <> MkSetBy y = MkSetBy (x <> y)
instance (HasField f a b, Ord b) => Monoid (SetBy f b a) where
mempty = empty
instance (Show a) => Show (SetBy f b a) where
show (MkSetBy m) = show (Map.elems m)
{-
λ data State = State { state :: String, population :: Int } deriving Show
λ :seti -XDataKinds
λ SetBy.singleton @"state" (State "IN" 400)
[State {state = "IN", population = 400}]
λ SetBy.singleton @"state" (State "IN" 400) <> SetBy.singleton (State "IN" 400)
[State {state = "IN", population = 400}]
λ SetBy.singleton @"state" (State "IN" 400) <> SetBy.singleton (State "IN" 400) <> SetBy.singleton (State "CA" 50000)
[State {state = "CA", population = 50000},State {state = "IN", population = 400}]
-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment