
#12160: MonadFail instance for (Either String)? -------------------------------------+------------------------------------- Reporter: lexi.lambda | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: libraries | Version: 8.0.1 (other) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by Iceland_jack): Do you have a use case? I don't think details of string conversion belong in the `MonadError` instances and if you want instances like `MonadFail (Either ByteString)` that brings up issues of encoding, truncation (as `IsString ByteString`). It would complicate the type class and make inference fail in basic examples {{{#!hs data Foobar = Foo Int | Bar String instance MonadFail (Either String) where fail = Left }}} {{{ ghci> do Bar a <- Right (Foo 42) ghci| pure a ghci| <interactive>:13:1: error: • Ambiguous type variable ‘a0’ arising from a use of ‘print’ prevents the constraint ‘(Show a0)’ from being solved. ... }}} I argue most users would prefer {{{#!hs instance String ~ a => MonadFail (Either a) where fail = Left }}} {{{ ghci> do Bar a <- Right (Foo 42) ghci| pure a ghci| Left "Pattern match failure in do expression at <interactive>:11:4-8" }}} and if they want to avoid `String` entirely they can use `throwError` from [https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad- Except.html#t:MonadError MonadError] and be polymorphic in the error {{{#!hs throwError :: e -> Either e a throwError @String @(Either _) :: String -> Either String a throwError @Text @(Either _) :: Text -> Either Text a throwError @[Bool] @(Either _) :: [Bool] -> Either [Bool] a }}} {{{#!hs instance MonadError e (Either e) where throwError :: e -> Either e a throwError = Left catchError :: Either e a -> (e -> Either e a) -> Either e a Left l `catchError` h = h l Right r `catchError` _ = Right r }}} ---- This may be what you were aiming at, {{{#!hs instance IsString str => MonadFail (Either str) where fail :: String -> Either str a fail = Left . fromString -- Left "Pattern match failure in do expression at /tmp/tH2v.hs:16:3-7" str :: Either String String str = do Bar a <- Right (Foo 42); pure a -- Left "Pattern match failure in do expression at /tmp/tH2v.hs:21:3-7" txt :: Either Text String txt = do Bar a <- Right (Foo 42); pure a -- Left (Const (Identity "Pattern match failure in do expression at /tmp/tH2v.hs:26:3-7")) cnst :: Either (Const (Identity [Char]) ()) String cnst = do Bar a <- Right (Foo 42); pure a }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12160#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler