Обработка ошибок в Haskell с любой монадой - PullRequest
6 голосов
/ 03 июня 2009

У меня есть функция, которая проверяет, является ли тип подтипом другого типа:

st :: Monad m => Map String Type  -- ^type environment
   -> Set (Type, Type) -- ^assumed subtypes
   -> (Type, Type) -- ^we are checking if lhs <: rhs      
   -> m (Set (Type, Type))

Я хочу заняться обработкой ошибок. У меня есть следующее определение:

instance Monad (Either String) where
  return v = Right v
  fail s = Left s
  (Left s) >>= _ = Left s
  (Right v) >>= f = f v

Иногда я могу обрабатывать ошибки, рассматривая результат st как Either. Например, следующая функция работает, и получает мне сообщения, которые появляются в результате вызова «fail» внутри st:

isSubType env cs t1 t2 = result where
  result = case st env (S.empty) (t1, t2) of
    Left msg -> Left msg
    Right rel -> Right ()

Теперь я нахожусь внутри st и хочу рекурсивно это назвать. По какой-то причине следующий код, вложенный глубоко в st:

  let do_t1 rel t1 = case st env rel (t1, t2) of
        Left msg -> fail $ printf "type %s in the union is not a subtype\
                           \ of the rhs, %s, because: %s" (renderType t1)
                           (renderType t2) (show msg)
        Right rel -> return rel

Не проверяет тип, но выдает следующую ошибку:

 No instance for (Monad (Either t))
      arising from a use of `st'
                   at src/TypedJavaScript/Types.hs:386:24-42
    Possible fix: add an instance declaration for (Monad (Either t))

Почему обработка результата st как Either работает вне 'st', но не внутри? Как я могу изменить свой код так, чтобы он тоже работал внутри?

1 Ответ

5 голосов
/ 03 июня 2009

Я думаю, проблема в том, что вы звоните show msg, где вы должны просто использовать msg В результате компилятор не может сделать вывод, что вы имели в виду Either String; все, что он знает, это то, что у вас есть Either t, где выполняется ограничение Show t. Замена show msg на msg должна исправить это.

...