Say I have a monad that emits soft failure through Writer. A simplified version goes like this (for the record, I'm using GHC 9.0.2):
{-# LANGUAGE BlockArguments #-}{-# LANGUAGE FlexibleContexts #-}-- {-# LANGUAGE GADTs #-}{-# LANGUAGE ScopedTypeVariables #-}module Lib whereimport Control.Monad.Writer.CPSimport Data.Maybeverify :: MonadWriter [String] m => some -> args -> m ()verify _ _ = fix \(_ :: m ()) -> do let warn = tell . (: []) a = Just 1 :: Maybe Int b = Just [1, 23] :: Maybe [Int] c = Just (id :: forall a. a -> a) -- isJust' :: String -> Maybe a -> m () isJust' tag v = unless (isJust v) do warn $ tag <> " is Nothing" isJust'"a" a isJust'"b" b isJust'"c" c
All goes fine until I add GADTs
extension, then GHC fails to find the most general type for isJust'
:
• Couldn't match type ‘[Int]’ with ‘Int’ Expected: Maybe Int Actual: Maybe [Int]• In the second argument of ‘isJust'’, namely ‘b’ In a stmt of a 'do' block: isJust'"b" b In the expression: do let warn = tell . (: []) a = ... .... isJust'"a" a isJust'"b" b isJust'"c" c |22 | isJust'"b" b | ^/var/tmp/demo/src/Lib.hs:23:17: error:• Couldn't match type ‘a0 -> a0’ with ‘Int’ Expected: Maybe Int Actual: Maybe (a0 -> a0)• In the second argument of ‘isJust'’, namely ‘c’ In a stmt of a 'do' block: isJust'"c" c In the expression: do let warn = tell . (: []) a = ... .... isJust'"a" a isJust'"b" b isJust'"c" c |23 | isJust'"c" c | ^
At which point I have to uncomment type annotation for isJust'
to get this to type check - I'm wondering what is at play here, I don't think I'm using any GADTs features?
Side note 1: I usually just slam a NoMonomorphismRestriction
to see if it helps, it didn't.
Side note 2: That use of fix
is just for getting a hold on that m
in the presence of ScopedTypeVariables
- a side question is whether there are better ways to do this without relying on verify
having an explicit type signature (say this function is defined inside an instance).