如何打破"打破"在haskell中的IO动作

时间:2014-08-06 02:37:41

标签: haskell

我想在haskell中使用“返回”(使用命令式语言)功能。

E.g。

main = do
  let a = 10
  print a
--  return this function
  print $ a + 1

我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:2)

您可以使用Exceptions

在某种程度上模仿这一点
{-# LANGUAGE DeriveDataTypeable #-}
import Control.Exception
import Data.Typeable

data MyException = MyException deriving (Show, Typeable)
instance Exception MyException

main = handle (\ MyException -> return ()) $ do
  let a = 10 :: Int
  print a
  throwIO MyException
  print $ a + 1         -- never gets executed

你也可以使用ContT or ErrorT monad transformers来完成它,虽然它们可能有点笨拙。

答案 1 :(得分:2)

首先,让我首先警告说,尝试将命令式构造转换为Haskell可能会导致代码不是惯用的,难以编写且难以阅读。仅仅因为你可以通过使用一些monad变换器来模拟一些构造,这并不意味着实际上应该这样做。

话虽如此,这是使用Control.Monad.Cont.ContT提前返回的一个例子。下面的代码模拟了几个for循环中的命令性返回。

正如Rufflewind警告的那样,这可能会变得笨拙。单独callCC的类型(下面未显示)可能非常令人费解。

import Control.Monad.Cont

search :: Int -> IO (Maybe (Int,Int))
search x = runContT (callCC go) return
  where go earlyReturn = do
           forM_ [10..50] $ \i -> do
              lift $ putStrLn $ "Trying i=" ++ show i
              forM_ [10..50] $ \j -> do
                lift $ putStrLn $ "Trying j=" ++ show j
                when (i * j == x) $ do
                   lift $ putStrLn $ "Found " ++ show (i,j)
                   earlyReturn $ Just (i,j)
           return Nothing