我正在尝试实现这个练习,但在 Haskell 中
编写一个称为转换的高阶函数,该函数应用相同的函数 函数,以将其转换为新值的列表的所有元素。 但是,如果在转换 列表,则应使用给定列表中的原始值。为 实例
- 变换 (fn x => 15div x( [1,3,0,5] -------------------- val it = [15,5,0,3] : int list
当涉及到哈斯克尔的异常处理时,我真的很困惑,我不明白。 我有我编写的这个基本代码,但它必须适应与异常处理程序一起使用。
import Control.Exception
import System.Environment
import System.IO
data MyError = Error deriving Show
Instance Exception MyError
transform :: (a -> a) -> [a] -> [a]
transform f [] = []
transform f (x:xs) = [f x] ++ transform f [xs]
关于如何抛出和捕获此特定异常,我有几个问题,以便程序不会因此而停止其处理链。
我已经阅读了文档,其中说:
如果要在出现异常时进行一些清理 提出,最后使用,括号或异常。在 例外并做其他事情,最好的选择是使用 尝试家庭。...除非您正在从异步恢复 例外,在这种情况下,使用 catch 或 catchJust。
所以我猜我最好的选择可能是使用尝试或捕获语句? 但我真的不确定如何编写/组织它。
我真的是函数式编程的新手,非常感谢所有有助于更好地理解这个问题。
你被要求做的事情不是你应该做的事情。但是,如果我真的必须编写一个由于某种原因处理异常而不在 IO 中的函数,我会安装spoon
然后编写以下内容:
import Control.Spoon (teaspoon)
import Data.Maybe (fromMaybe)
transform :: (a -> a) -> [a] -> [a]
transform f = map $ x -> fromMaybe x . teaspoon $ f x
如果没有第三方库,您可以改为编写以下内容:
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Exception (catch, evaluate, SomeException)
import System.IO.Unsafe (unsafePerformIO)
transform :: (a -> a) -> [a] -> [a]
transform f = map $ x -> unsafePerformIO $ evaluate (f x) `catch` (_ :: SomeException) -> pure x
为了强调:我不乐意看到其中任何一个在生产中完成,主要是由于unsafePerformIO
(teaspoon
内部使用(。但是,如果您被允许将结果放在IO
中,那么第二种解决方案(但没有unsafePerformIO
(是可以接受的(尽管捕获异步异常也很糟糕,因此您需要比SomeException
更细微的东西(。