[GHC] #12160: MonadFail instance for (Either String)?

GHC ghc-devs at haskell.org
Wed Jun 8 08:31:40 UTC 2016


#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


More information about the ghc-tickets mailing list