首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么程序能很好地工作在双类型而不是浮点类型?

为什么程序能很好地工作在双类型而不是浮点类型?
EN

Stack Overflow用户
提问于 2013-12-20 22:06:24
回答 1查看 89关注 0票数 1

嗨,我是haskell编程的新手,我写了这段代码:

代码语言:javascript
复制
f :: a->Bool
f x = True

g :: a->Bool 
g x = False

class P a where
   func :: a->Bool

instance P Integer where
   func x = f x

instance P Float where
   func x = g x

如果我以func Ghci的形式调用函数func 23.3,则返回以下错误:

<interactive>:6:6: Ambiguous type variable a0' in the constraints: (Fractional a0) arising from the literal 23.3' at <interactive>:6:6-9 (P a0) arising from a use of func' at <interactive>:6:1-4 Probable fix: add a type signature that fixes these type variable(s) In the first argument of func', namely 23.3' In the expression: func 23.3 In an equation for it': it = func 23.3

如果我以整数作为参数调用func,则代码可以正常工作。如果我将P的Float实例替换为Double实例,则代码将正确地用于调用func 23.3。为什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-12-20 22:10:48

这就是臭名昭著的摩诺主义限制。GHCi不知道具体将23.3转换为哪种类型,并且存在多种Fractional a数据类型(特别是DoubleFloat)。

您可以用

代码语言:javascript
复制
> :set -XNoMonomorphismRestriction

或者更好

代码语言:javascript
复制
> func (23.3 :: Float)

之所以如此,是因为文字23.3具有类型。

代码语言:javascript
复制
> :type 23.3
23.3 :: Fractional a => a

而不是更具体的类型,如FloatInt。这实际上允许您实现自己的类型,这些类型可以由数字文本表示(有时是一个方便的技巧)。不幸的是,它给出了一个相当无用的错误信息,使大多数初学者感到困惑。但是编译器必须有特定的类型,因为您还可以添加

代码语言:javascript
复制
instance P Double where
    func x = undefined

然后,它必须决定将哪个func实例用于像23.3这样的文本。最好的做法是指定您使用的是内联类型,就像我在上面展示的那样。

它在GHCi中与Double一起工作的原因可能是因为GHCi有时会为了方便而试图将类型强制转换成更具体的东西。这就是为什么如果你要

代码语言:javascript
复制
> let x = [1..]
> :type x
x :: [Integer]

相反,x应该具有(Enum a, Num a) => [a]类型。如果启用了单体主义限制(默认情况下),GHCi将尝试使类型与IntegerDoubleIO一起工作,而不是Integral a => aDouble a => aMonad m => m。但并不是每一种情况都很好。

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

https://stackoverflow.com/questions/20712679

复制
相关文章

相似问题

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