@@ -0,0 +1,54 @@
1+module Record.Studio.SingletonRecord where
2+
3+import Prelude
4+
5+import Data.Symbol (class IsSymbol)
6+import Prim.Row as Row
7+import Prim.RowList (class RowToList)
8+import Prim.RowList as RL
9+import Prim.TypeError (class Fail, Text)
10+import Type.Proxy (Proxy(..))
11+import Unsafe.Coerce (unsafeCoerce)
12+
13+class SingletonRecord :: forall k1 k2 k3. k1 -> k2 -> Row Type -> k3 -> Constraint
14+class SingletonRecord key value rec recRL | rec -> key value recRL where
15+ -- | Get the key of a record with only one field as a `Proxy`
16+ key :: Record rec -> Proxy key
17+
18+instance
19+ ( RowToList rec recRL
20+ , SingletonRecordFields key a rec recRL
21+ ) =>
22+ SingletonRecord key a rec (RL.Cons key a RL.Nil) where
23+ key = singletonRecordFields (Proxy :: Proxy recRL)
24+else instance (Fail (Text "The record must have exactly one field")) => SingletonRecord key a rec recRL where
25+ key _ = unsafeCoerce unit
26+
27+class SingletonRecordFields :: forall k1 k2. k1 -> Type -> Row Type -> k2 -> Constraint
28+class
29+ SingletonRecordFields key value rec recRL
30+ | rec -> key value
31+ where
32+ singletonRecordFields :: Proxy recRL -> { | rec } -> Proxy key
33+
34+instance
35+ ( RowToList rec (RL.Cons key a RL.Nil)
36+ , Row.Cons key a () rec
37+ , IsSymbol key
38+ ) =>
39+ SingletonRecordFields key a rec (RL.Cons key a RL.Nil) where
40+ singletonRecordFields _ _ = (Proxy :: Proxy key)
41+
42+instance
43+ ( Fail ErrorMsg
44+ ) =>
45+ SingletonRecordFields key a rec RL.Nil where
46+ singletonRecordFields _ _ = unsafeCoerce unit
47+
48+else instance
49+ ( Fail ErrorMsg
50+ ) =>
51+ SingletonRecordFields key a rec (RL.Cons key a (RL.Cons key1 a1 rl)) where
52+ singletonRecordFields _ _ = unsafeCoerce unit
53+
54+type ErrorMsg = (Text "The record provided to `key` must have exactly one field")