I have a newtype which takes a parameterized type,
newtype MockState m = MockState { apiState :: {api1 :: m Int, api2:: m String} }
derive instance newtypeMockState :: Newtype (MockState m) _
I have a function that creates a ref out of some field,
createRef :: forall s a b r r' rem
. IsSymbol s
=> Newtype (MockState Identity) {apiState :: Record r}
=> Row.Cons s (Identity a) r' r
=> Proxy s
-> MockState Identity
-> Effect (Ref.Ref a)
createRef pxy (MockState mockState)= do
let (Identity val) = Record.get pxy mockState.apiState
Ref.new val
Why the compiler can't resolve the constraint?
No type class instance was found for
Prim.Row.Cons s4
(Identity a5)
t2
( cla :: Identity String
, login :: Identity Int
)
When I pass Record r directly insted of my newtype, it compiles without any issue... and the below also works..
createRef :: forall s a b mock r' r rem
. IsSymbol s
=> Newtype mock {apiState :: Record r}
=> Row.Cons s (Identity a) r' r
=> Proxy s
-> mock
-> Effect (Ref.Ref a)
createRef pxy r = do
let (Identity val) = Record.get pxy (unwrap r).apiState
Ref.new val
but how? Literally the first one and last are same right? Why the compiler can't infer r?
This is because the compiler can't see a connection between your
Newtypeconstraint and the pattern(MockState mockState). These are technically unrelated. TheNewtypeclass is not magic enough for this.So
mockStateis inferred to be of type{ apiState :: Record r1 }, wherer1is distinct fromr, and therefore constraintCons s (Identity a) r' rdoes not apply tor1.In order to get the right type inference, you have to unwrap your newtype by utilizing the
Newtypeconstraint itself. Then the unwrapped value will have type{ apiState :: Record r }, and theConsconstraint will apply.You can do this by using the
unwrapfunction: