Christophe De Troyer
Christophe De Troyer

Reputation: 2922

Monadic guard with Either

I am implementing an typechecker in Haskell. The main signature of typechecking functions is

judge :: Term -> StateT Context (Either String) Type

If the typechecker fails, it returns lift $ Left "Something went wrong".

For example, a function to typecheck an if (pseudo):

judge (ExpIf test cons alt) =
  do
    testT <- judge test
    consT <- judge cons
    altT  <- judge alt
    guard $ consT == altT

Originally this code was written as follows.

judge (ExpIf test cons alt) =
  do
    testT <- judge test
    consT <- judge cons
    altT  <- judge alt
    if altT == consT
       then return consT
       else lift $ Left "Types for cons and alt do not match"

Given that, if I have a few guards, I would have too much indendation so I changed my code to use guards.

I know that the return type of the guard expression is () but in the background it makes my Either monad fail as well by returning Left "". Is there any way I could pass a string to the guard?

judge (ExpIf test cons alt) =
  do
    testT <- judge test
    consT <- judge cons
    altT  <- judge alt
    guard (consT == altT) "types of cons and alt should match!"

Upvotes: 3

Views: 2320

Answers (1)

Daniel Wagner
Daniel Wagner

Reputation: 152707

You can combine when/unless with either fail or throwError (depending on your monad's particular implementation of these class-polymorphic functions). For example, you might write:

unless (consT == altT) (throwError "types of cons and alt should match")

Upvotes: 4

Related Questions