Created
August 19, 2015 02:36
-
-
Save 7shi/d2951a7f40be7e827c2f to your computer and use it in GitHub Desktop.
[Haskell] 継続モナドによる脱出をEitherモナドで模倣
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Data.Char | |
import Control.Monad.Cont | |
fun :: Int -> String | |
fun n = (`runCont` id) $ do | |
str <- callCC $ \exit1 -> do -- "exit1" を定義 | |
when (n < 10) $ exit1 $ show n | |
let ns = map digitToInt $ show $ n `div` 2 | |
n' <- callCC $ \exit2 -> do -- "exit2" を定義 | |
when (length ns < 3) $ exit2 $ length ns | |
when (length ns < 5) $ exit2 n | |
when (length ns < 7) $ do | |
let ns' = map intToDigit $ reverse ns | |
exit1 $ dropWhile (== '0') ns' -- escape 2 levels | |
return $ sum ns | |
return $ "(ns = " ++ show ns ++ ") " ++ show n' | |
return $ "Answer: " ++ str | |
fun' n = -- Either で模倣 | |
let str = either id id $ do | |
let exit1 = Left -- "exit1" を定義 | |
when (n < 10) $ exit1 $ show n | |
let ns = map digitToInt $ show $ n `div` 2 | |
n' <- either id id $ do | |
let return = Right . Right -- "return" を再定義 | |
exit1 = Left . Left -- "exit1" を再定義 | |
exit2 = Left . Right -- "exit2" を 定義 | |
when (length ns < 3) $ exit2 $ length ns | |
when (length ns < 5) $ exit2 n | |
when (length ns < 7) $ do | |
let ns' = map intToDigit $ reverse ns | |
exit1 $ dropWhile (== '0') ns' -- escape 2 levels | |
return $ sum ns | |
return $ "(ns = " ++ show ns ++ ") " ++ show n' | |
in "Answer: " ++ str | |
main = do | |
forM_ [0..7] $ \i -> do | |
let n = 5 * 10 ^ i | |
f1 = fun n | |
f2 = fun' n | |
print (i, n, f1 == f2, f1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
出典: Continuation モナド - モナドのすべて