假设下面是代码。是否有更快的方法从findSerial中获取上下文值,而不是编写像outOfContext这样的函数?根本的问题是:一个人通常会在上下文中使用函子、应用程序、Monoids和Monads来完成任务,还是把它从上下文中去掉并应用通常的非上下文计算方法更好。简单地说:我不想完全错误地学习Haskell,因为它需要足够的时间。
import qualified Data.Map as Map
type SerialNumber = (String, Int)
serialList :: Map.Map String SerialNumber
serialList = Map.fromList [("belt drive",("BD",0001))
,("chain drive",("CD",0002))
,("drive pulley",("DP",0003))
,("drive sprocket",("DS",0004))
]
findSerial :: Ord k => k -> Map.Map k a -> Maybe a
findSerial input = Map.lookup input
outOfContext (Just (a, b)) = (a, b)发布于 2018-08-01 06:23:31
假设我正确理解了它,我认为您的问题本质上归结为“编写和使用部分函数在Haskell中是惯用的吗?”(这是outOfContext函数,因为它只是内置的部分函数fromJust的一种专门形式)。这个问题的答案是一个响亮的no。尽可能避免部分函数,使用它们的代码通常可以重构为不使用它们的代码。
避免部分功能的原因是它们自愿地损害了类型系统的有效性。在Haskell中,当一个函数具有X -> Y类型时,通常假定提供给它一个X实际上会产生一个Y,并且它不会完全执行其他事情(即崩溃)。如果您的函数并不总是成功,那么通过编写X -> Maybe Y来反映该类型的信息会迫使调用方以某种方式处理Nothing情况,并且它可以直接处理它,或者将故障进一步推迟到调用方(也可以生成一个Maybe)。这很好,因为这意味着打字机程序不会在运行时崩溃。程序可能仍然有逻辑错误,但是即使在运行程序之前就知道它不会爆炸,这仍然是相当不错的。
部分函数将此保证抛出窗口。如果函数的先决条件被意外违反,任何使用部分函数的程序都会在运行时崩溃,而且由于这些先决条件没有反映在类型系统中,所以编译器不能静态地执行这些先决条件。在编写程序时,程序可能在逻辑上是正确的,但不强制使用类型系统的正确性,进一步的修改、扩展或重构很容易错误地引入错误。
例如,程序员可能会编写表达式。
if isJust n then fromJust n else 0这肯定不会在运行时崩溃,因为fromJust的前提条件总是在调用之前进行检查。但是,类型系统不能强制这样做,进一步的重构可能会交换if的分支,或者它可能会将fromJust n完全移动到程序的另一个部分,并且意外地忽略了isJust检查。该程序仍将编译,但在运行时可能会失败。
相反,如果程序员避免使用与case的显式模式匹配或maybe和fromMaybe之类的总函数来避免部分函数,则可以将上面的复杂条件替换为以下内容
fromMaybe 0 n这不仅更加清晰,而且确保任何意外的误用都会使打字机无法正常运行,而且潜在的错误将被更早地检测出来。
关于类型系统如何成为一个强大的盟友的一些具体例子,如果您只坚持全面的功能,以及一些很好的食物来思考如何将您的域的类型安全编码到Haskell的类型系统中,我强烈建议阅读Matt的精彩博客文章安全背四型,它更深入地探讨了这些想法。此外,它还强调了如何使用Maybe作为失败的全捕获表示是很尴尬的,它还展示了如何使用类型系统来执行先决条件,以避免在整个系统中传播Maybe。
https://stackoverflow.com/questions/51626308
复制相似问题