Reputation: 2922
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 guard
s.
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
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