[Haskell-cafe] Two mysteries
Tom Ellis
tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk
Sun Aug 28 17:31:18 UTC 2022
On Sun, Aug 28, 2022 at 09:36:56AM -0700, Henry Laxen wrote:
> class State a where
> type StateKey a :: *
> type StateValue a :: *
> lensTmap :: Functor f => Lenstype f a (TMap (StateKey a) (StateValue a))
> lensKey :: Functor f => Lenstype f a (StateKey a)
> lensCounter :: Functor f => Lenstype f (StateValue a) Int
>
> updateState state f = liftIO $ do
> let
> key = state ^. lensKey -- read the key
> mutable = state ^. lensTmap -- find the TVar of the TMap
> withKey key (\(Just x) -> x & lensCounter %~ f) mutable -- update it
>
> -- THE FIRST MYSTERY: If I use the inferred type explicitly for updateState
> -- above, this no longer compiles. I get a "could not deduce" error
> -- reproduced below:
>
> -- xupdateState
> -- :: (MonadIO m, Ord (StateKey s), State s, State a,
> -- StateValue s ~ StateValue a) =>
> -- s -> (Int -> Int) -> m ()
> -- xupdateState state f = liftIO $ do
> -- let
> -- key = state ^. lensKey -- read the key
> -- mutable = state ^. lensTmap -- find the TVar of the TMap
> -- withKey key (\(Just x) -> x & lensCounter %~ f) mutable -- update it
AllowAmbiguousTypes is what's allowing you to get tangled into this
knot. I suggest you don't enable that extension unless you feel
confident you are equipped for axe warfare.
The behaviour here is as though the type checker has turned
`lensCounter` in the body into `lensCounter @a` for a fresh type
variable `a`, and then applied the necessary constraints to the
context. Normally the type checker would notice that `a` is ambiguous
and refuse to continue. AllowAmbiguousTypes defers that check to the
use site. That means I don't think it makes any difference to you,
because even though `updateState` with inferred type signature will
compile I bet you can't use it. Give it a try! I guess you'll get an
"ambiguous type" error at the use site.
Tom
More information about the Haskell-Cafe
mailing list