2016-12-01 16 views
1

Я все еще новичок в Haskell. Каков наилучший способ отличить ошибки? В настоящее время я использую монаду maybe, но она может только «представлять одно состояние ошибки».Отличительные ошибки в haskell

Следующий фрагмент кода поместит мой вопрос в контекст.

pulOh :: Seq   -- input X O sequence 
     -> Int   -- split point real index 
     -> Maybe Seq 
pulOh xs n   = 
    case (\(f,l)->(tlTrn f, hdTrn l)) (splSq xs n) of   -- split and process at index 
    (Nothing, _) -> Nothing        -- first failed 
    (_, Nothing) -> Nothing        -- last failed 
    (Just f,Just l) -> Just (f ++ l)      -- both parts passed 

Я хотел бы результат, чтобы быть в состоянии различить, если вызов не для fst или snd. Короткое замыкание в случае неудачи fst сбой.

ответ

4

Использование Either. Это в основном то же самое, что и Maybe с параметризованным конструктором Nothing, или, другими словами, Maybe a изоморфен Either() a. Заменив ошибку блока «()» на пользовательский тип тега ошибки, вы можете сделать разные случаи отказа различными.

pulOh :: Seq -> Int -> Either String Seq 
pulOh xs n = case tlTrn *** hdTrn $ splSq xs n of 
    (Nothing, _) -> Left "first failed" 
    (_, Nothing) -> Left "last failed" 
    (Just f,Just l) -> Right $ f ++ l 

(я взял на себя смелость заменить, что лямбда с *** «параллельного трубопровода»)

+0

Спасибо это работает! Есть ли что-то похожее на 'fmap', которое я могу использовать для обоих? – iluvAS

+2

@iluvAS 'fmap' работает на' Либо b', влияя только на правильные значения 'b'. (В библиотеках должно быть более общее 'dimap', но оно широко не используется) – chi

+2

Экземпляр' Either' для 'Data.Bifunctor' предоставляет' bimap fg (Left x) = Left (fx) 'и' bimap fg (Right y) = Right (gy) '. 'dimap' - это' Data.Profunctor' (который я недостаточно понимаю, чтобы комментировать дальше). – chepner