【问题标题】:Safe application in HaskellHaskell 中的安全应用
【发布时间】:2012-04-01 12:33:41
【问题描述】:

我有一段代码在列表单子中应用了一个函数。函数可能对其参数具有非详尽的模式匹配。因此,当应用该功能时,我可能会收到"Non-exhaustive pattern matching" 错误。我想把这个错误变成一个单子失败(在这种情况下,一个空列表)。换句话说,我希望获得与 Some Pattern Here <- some valuedo 块内失败时发生的情况类似的行为。

问题:有没有一种高效的方法来保证函数应用程序的安全?所谓高效,我的意思是类似于使应用的函数彻底匹配并显式失败。

【问题讨论】:

  • 问题不清楚。既然您在 list monad 中,为什么不只是在 do-construct 中进行模式匹配,或者在其他情况下使用显式 case 构造。最好贴个示例代码。

标签: exception haskell exception-handling functional-programming monads


【解决方案1】:

一种选择是使用spoon 将函数从引发异常的函数转换为返回Maybe a 值的函数。那么将Nothing 转换为[] 应该很简单。

【讨论】:

  • 我不确定 Spoon 是否应该被积极推广,看这个帖子 reddit.com/r/haskell/comments/acasn/…
  • 我可能不会冒险使用它。无论如何,我相信这是最接近我要求的。
  • 我觉得勺子不错。是的,它破坏了理论属性和东西,但是库的目的是处理糟糕的代码(无论如何,它的定义方式都没有与所述理论属性很好地配合)。当替代方案是从头开始重新实现(或者在这种情况下......解析和修复用户的代码 - bleh!)时,spoon 是一个很好的替代方案。
【解决方案2】:

嗯,也许有一个陷阱?但是,您应该在 IO monad 中工作:

import Prelude hiding (catch)
import Control.Monad (MonadPlus, mzero)
import Control.Exception (catch, SomeException)

data B = T | F
    deriving (Show)

f :: B -> B
f T = F

justCatch :: (MonadPlus m) => a -> IO (m a)
justCatch x = catch (x `seq` (return . return) x) handler
  where
    handler :: (MonadPlus m) => SomeException -> IO (m a)
    handler _ = return mzero

我不确定此解决方案可能存在的问题。乍一看它似乎有效,但我也想从知识渊博的 Haskellers 那里阅读一些意见。 我肯定不会在我的代码中使用这个解决方案:错误应该被这样对待,而不是隐藏它。

*Main> justCatch $ f T :: IO [B]
[F]
*Main> justCatch $ f F :: IO [B]
[]
*Main> justCatch $ f F :: IO (Maybe B)
Nothing
*Main> justCatch $ f T :: IO (Maybe B)
Just F
*Main> f T
F
*Main> f F
*** Exception: except.hs:8:1-7: Non-exhaustive patterns in function Main.f

【讨论】:

  • IO monad 不是一个选项。我尽量让我的代码保持纯净。
  • 据我所知,您只能使用catch 来处理类似的异常(这会迫使您在 IO 中工作)。如果您不想使用 Daniel 提出的勺子(使用不安全操作),恐怕您可能没有其他选择。
  • 好的,否定的答案仍然是答案。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多