首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Haskell的类型替换assert语句或其他语言的if检查

使用Haskell的类型替换assert语句或其他语言的if检查
EN

Stack Overflow用户
提问于 2010-07-10 17:49:24
回答 3查看 1.9K关注 0票数 13

对不起,如果这个问题很基本的话,我对Haskell还很陌生。假设我有一个函数只能处理黄金比率(1.618)中的两个数字,我如何定义myfun y的类型以只取黄金比率数字。如果我在程序中调用我的程序中没有黄金比率的数字(编译错误),会发生什么?如果没有黄金比率号的调用是通过用户输入在运行时进行的,会发生什么情况?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-07-10 18:21:33

您可能需要一个只能用黄金比率数字构造的ADT,然后编写myfun来接受该数据类型。

我假设Integer是一个基本类型,但您可以使用其他类型(例如: Double或Float),甚至可以是多态的。

1)制定ADT

代码语言:javascript
复制
module Golden (Gold, getGold, buildGold) where

data Gold = G Integer Integer

getGold :: Gold -> (Integer, Integer)
getGold (G x y) = (x, y)

buildGold :: Integer -> Integer -> Maybe Gold
buildGold x y
    | isGolden x y = Just (G x y)
    | otherwise    = Nothing

注意,这个模块导出Gold类型,但不导出构造函数(即不导出G)。因此,获得Gold类型值的唯一方法是使用buildGold执行运行时检查--但只执行一次--这样所有消费者都可以不用检查就使用黄金值,并将其假定为黄金比率。

2)使用ADT构建myfun

代码语言:javascript
复制
myfun :: Gold -> ???
myfun g = expr
  where (x, y) = getGold g

现在,如果您尝试使用一个非黄金数字(一个不是myfun类型的值)调用Gold,那么您将得到一个编译时错误。

要构建黄金数字,必须使用Recap函数buildGold函数,这将强制检查数字。

注意什么时候会被检查!您有一个编译时间保证myfun和您想要与Gold一起使用的所有其他函数总是被提供黄金比率。程序输入(来自用户、网络或任何地方)仍然需要运行时检查,这正是buildGold所提供的;显然,永远不会有一个程序能够保证人类不会输入一些不需要的东西。

在对你的问题的评论中给出的替代方案也值得考虑。如果您只需要一个函数,myfun,它就会失败,那么就只有myfun :: (Integer, Integer) -> Maybe ???了,那么ADT就有点重了。

票数 18
EN

Stack Overflow用户

发布于 2010-07-10 20:35:42

最简单的技术是使用智能构造器,它使用从Int到GoldenInt的函数,检查您的值是否处于所需的比率。

通过更多的努力,您可以使用类型级数来确保不需要运行时检查,但是,考虑到您是初学者,我将坚持使用智能构造函数方法。

汤姆上面的回答就是这个成语的一个例子。

票数 10
EN

Stack Overflow用户

发布于 2010-07-10 18:20:52

实际上,你能做的最好就是一次运行时检查。可能有一些类型级别的微积分,我不知道(见luqui的评论),但这在Haskell中是不实用的。

你可以使用断言,这就是你想要替换的东西,

代码语言:javascript
复制
checker :: a -> b -> Bool
checker x y = x * 1.618 `approxEqual` y

unsafeMyfun :: a -> b -> c
unsafeMyfun x y = assert (checker x y) (doRealThingWith a b)

或返回Maybe a (或Either err a)以避免无法在纯函数中捕获的异常,

代码语言:javascript
复制
myfun :: a -> b -> Maybe c
myfun x y = do
              guard $ checker x y
              return $ doRealThingWith x y

或者使用自定义的契约类型,如Tom的答案等。无论如何,在编译时不可能检查约束(编译时)。事实上,由于In,任何编译时约束都不能精确。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3220246

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档