John Doe
John Doe

Reputation: 65

Haskell: Working with errors/exceptions in Haskell

He guys, I have a problem. I have two functions in my Haskell program.

type Env =  String -> Int

emptyEnv :: Env
emptyEnv _ = error "Failed"

insertEnv :: String -> Loc -> Env -> Env
insertEnv s loc env = case env s of
                      (error "Failed") -> (\inp -> (if inp==s then loc else env s))
                      _ -> env

So my emptyEnv should always give an error message. With the other function insertEnv you can insert elements to Env. But therefore you need to check if Env is empty and this will display an error on screen. Now my question: The code above doesn't work because error "Failed" is not a case of env s in the function insertEnv. Do you have an idea how I handle the error properly so that you can insert elements to env?

Upvotes: 0

Views: 96

Answers (2)

ase
ase

Reputation: 13471

We usually handle failing functions in Haskell by them returning a Maybe type:

type Loc = Int
type Env = String -> Maybe Loc -- Here

emptyEnv :: Env
emptyEnv _ = Nothing

And for insertEnv we would write:

insertEnv :: String -> Loc -> Env -> Env
insertEnv s loc env inp =
  case env inp of
    Nothing ->
      if s == inp
        then Just loc
        else Nothing
    Just loc' -> Just loc'

Which follows your intended meaning by not making an insert update the Env. Another possibility for insertEnv is to "update" the environment:

insertEnv' :: String -> Loc -> Env -> Env
insertEnv' key loc env inKey
  | key == inKey = Just loc
  | otherwise = env inKey

If you're interested, both versions can be implemented using the First and Last wrappers from Data.Monoid.

import Data.Monoid

type Env' = String -> First Loc -- Choose First or Last here

emptyEnv' :: Env'
emptyEnv' _ = mempty

insertEnv' :: String -> Loc -> Env' -> Env'
insertEnv' s loc env inp =
  env inp <>
  if s == inp
    then pure loc
    else mempty

With some environment

env1 = insertEnv' "1" 2 (insertEnv' "1" 1 emptyEnv')

If you pick First with the above implementation you get

GHCI> env1 "1"
First {getFirst = Just 1}

or with Last

GHCI> env1 "1"
Last {getLast = Just 2}

Upvotes: 3

Benjamin Hodgson
Benjamin Hodgson

Reputation: 44634

With the other function insertEnv you can insert elements to Env. But therefore you need to check if Env is empty.

Why do you need to check if an environment is empty before you insert something into it? An environment containing the variable x is just a function that, if given the name x, returns the value to which x was bound.

insertEnv s loc env = \v -> if v == s then loc else env v

Upvotes: 2

Related Questions