简体   繁体   中英

using “default” declaration for overloaded numeric operations

I try to develop an embedded domain specific language in Haskell. I don't want to type signatures as ::Rational all the time, so I try to use a default declaration for my types:

corresponding section in Haskell report

This works correctly in this simple example:

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

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

main = do

print $ mag 1 1

Indeed we obtain sqrt(2) as a result. If we replace the default declaration by:

default ()

, we obtain errors at compilation as expected: the type of 2 is ambiguous.

Now let us consider a more complicated example:

{-# 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

I would expect it to work correctly, but we obtain errors concerning the ambiguous type of 2 . Why? How to make my default declaration work? And if I want to give the priority to Rational instead of Integer ? Indeed, this should be possible because we don't get any error below.

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

PS1: The answer may be related to

answer given to a question on Stack Overflow

but I don't know in which way.

PS2: I already asked the question one week ago on Haskell-Cafe:

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

But as I obtained no answer, I ask the question here.

Haskell is very conservative about type class defaulting: it only chooses a default instance of classes defined in the Prelude. In your case, there is a Foo constraint on the type of the literal 2, so the compiler won't choose a default instance for it.

You can declare types in a syntactically lighter way by writing monomorphic functions. For example, the following compiles without errors:

rat :: Rational -> Rational
rat x = x

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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