繁体   English   中英

对重载的数值操作使用“默认”声明

[英]using “default” declaration for overloaded numeric operations

我尝试在Haskell中开发嵌入式领域特定语言。 我不想一直将签名键入为::Rational ,所以我尝试为我的类型使用默认声明:

Haskell报告中的相应部分

在以下简单示例中,这可以正常工作:

default (Integer, Double) -- "default default"

mag :: Float -> Float -> Float
mag x y = sqrt( x^2 + y^2 )

main = do

print $ mag 1 1

实际上,我们获得了sqrt(2)作为结果。 如果我们将默认声明替换为:

default ()

,我们会按预期在编译时获得错误: 2的类型不明确。

现在让我们考虑一个更复杂的示例:

{-# LANGUAGE FlexibleInstances #-}
import Prelude hiding ((^^))
import Data.Ratio

default (Integer, Rational, Double)

class (Num a) => Foo a where
    (^^) :: Num b => b -> a -> b

instance Foo Rational where
    (^^) x r = x ^ n
        where n = 2*numerator r -- dummy calculation

instance Foo Integer where
    (^^) x n = x ^ n

mag :: Float -> Float -> Float
mag x y = sqrt( x ^^ 2 + y ^^ 2 )

main = do
print $ mag 1 1

我希望它可以正常工作,但是我们会得到有关2的歧义类型的错误。 为什么? 如何使我的默认声明生效? 如果我要优先考虑Rational而不是Integer 确实,这应该是可能的,因为下面没有任何错误。

$ ghci
> import Data.Ratio
> 2::Rational
2 % 1

PS1:答案可能与

对堆栈溢出问题的答案

但我不知道用哪种方式。

PS2:一周前,我已经在Haskell-Cafe上问过这个问题:

http://www.haskell.org/pipermail/haskell-cafe/2013-September/108956.html

但是,由于我没有得到答案,我在这里提出问题。

Haskell对于类型类默认设置非常保守:它仅选择Prelude中定义的类的默认实例。 在您的情况下,文字2的类型存在Foo约束,因此编译器不会为其选择默认实例。

您可以通过编写单态函数以语法上更轻松的方式声明类型。 例如,以下编译无错误:

rat :: Rational -> Rational
rat x = x

mag :: Float -> Float -> Float
mag x y = sqrt( x ^^ rat 2 + y ^^ rat 2 )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM