【发布时间】:2020-09-10 12:10:56
【问题描述】:
我正在尝试实现这个 excersive,但在 Haskell 中
编写一个名为 transform 的高阶函数,它应用相同的 作用于列表的所有元素,将其转换为新值。 但是,如果在转换 列表,应使用给定列表中的原始值。为了 实例
- 变换 (fn x => 15 div x) [1,3,0,5] -------------------- val it = [15,5, 0,3] : 整数列表
当谈到 haskell 中的异常处理时,我真的很困惑,我不明白。 我已经编写了这个基本代码,但它必须适应异常处理程序。
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]
关于如何抛出和捕获这个特定异常,我有几个问题,以便程序不会因此而停止其处理链。
我已经阅读了文档,上面写着:
如果您想在出现异常的情况下进行一些清理 引发,使用 finally、括号或 onException。恢复后 例外并做其他事情,最好的选择是使用其中之一 尝试家庭。 ...除非您正在从异步中恢复 异常,在这种情况下使用 catch 或 catchJust。
所以我猜我最好的选择可能是使用 try 或 catch 语句? 但我不太确定如何编写/组织它。
我真的是函数式编程的新手,非常感谢所有有助于更好地理解这个问题的帮助。
【问题讨论】:
-
这个练习从何而来?它要求您做的事情并不是您在 Haskell 中真正应该做的事情。
-
它的练习取自《编程语言基础》,第二版,第 5 章(专门针对函数式语言的那一章)。只是它是为标准 ML 设计的,我们被要求使用 haskell 来代替
-
类型必须是
(a -> a) -> [a] -> [a],还是至少可以是(a -> a) -> [a] -> IO [a]? -
顺便说一句,如果你被零除,Haskell 将抛出的错误不会是你的
MyError类型。 -
我不知道标准 ML 是如何做到的,但是在 Haskell 中封装错误的一种常见方法是使用
Maybe类型。您将创建您的函数transform :: (a -> Maybe a) -> [a] -> [a],它的第一个参数将通过返回Nothing来指示“异常”。这样你就不必将它放在IO中,因为大多数“异常”都可以在没有IO的情况下使用Maybe之类的东西被抛出和处理(编写函数safeDiv :: Int -> Int -> Maybe Int可能是一个值得练习的练习)当div出错时返回Nothing)。