sarashino
@sarashino has joined the channel
caller x= do
case someFunc x of
Left err -> print err
Right y -> ..
someFunc:: MyType -> Either String OtherType
someFunc mt = do
first <- SomeEitherFunc mt
second <- AnotherEitherFunc first
…
case SomeEitherFunc mt of
Left err -> Left ( "from SomeEitherFunc:" ++ err)
Data.EitherR.fmapL 関数を使って頑張るしかないでしょう。
case SomeEitherFunc mt of
Left err -> Left ( "from SomeEitherFunc:" ++ err)
デバッグや障害時の原因究明のためならロガーをしこむのが順当な対応ですかね
haskell
ePrefix :: String -> Either String r -> Either String r
ePrefix pfx (Left orig) = Left (pfx ++ orig)
ePrefix _ r = r
someFunc:: MyType -> Either String OtherType
someFunc mt = do
first <- ePrefix "someEitherFunc" $ someEitherFunc mt
second <- ePrefix "anotherEitherFunc" $ anotherEitherFunc first
caller x= do
case someFunc x of
Left err -> print err
Right y -> print y
type MyType = Int
type OtherType = String
someFunc:: MyType -> Either MyException OtherType
someFunc mt = do
first <- someEitherFuncWithException mt
second <- anotherEitherFuncWithException first
return second
where
someEitherFuncWithException = convert SomeEitherError . someEitherFunc
anotherEitherFuncWithException first = convert AnotherEitherFuncError (anotherEitherFunc first)
someEitherFunc _ = Left "wrong"
anotherEitherFunc _ = Right "Correct!"
data MyException = SomeEitherError | AnotherEitherFuncError
deriving Show
convert :: MyException -> Either String a -> Either MyException a
convert myException (Left _) = Left myException
convert _ (Right other) = return other
import GHC.Stack
throw :: HasCallStack => String -> Either (CallStack, String) a
throw msg = Left (popCallStack callStack, msg)
foo :: HasCallStack => Either (CallStack, String) ()
foo = throw "err"
bar :: HasCallStack => Either (CallStack, String) ()
bar = throw "err"
main = case foo >> bar of
Left (e, msg) -> do
putStrLn $ prettyCallStack e
putStrLn msg
Right a -> print a
CallStack (from HasCallStack): foo, called at stack.hs:12:13 in main:Main err
readHoge :: Monad m => (FilePath -> m String) -> m String readHoge readF = do hogeContent <- readF "hoge" return $ "Hoge: " ++ hogeContent
readFile っぽくふる舞う関数をパラメーターとして受け取れるようにすることで、 IO に依存した処理をテストしやすくする、ということを私はよくやるのですが、その際にテスト用のファイルシステムの実装が必要となるのです。