简体   繁体   中英

How to tell GHC what fromIntegral should do

data N_ary = N_ary Int String Int deriving Eq

stores numbers to various bases. For example 15 to the bases 2, 10, and 16 are N_ary 1 "1111" 2 , N_ary 1 "15" 10 , and N_ary 1 "F" 16 respectively. (The first field is -1, 0, or 1 as a sign.)

I defined an operator infixl 5 ~> for converting things into N_ary objects and a class for convertible types.

class N_aryAble a where
  (~>) :: a -> Int -> N_ary

I had no problems with instance N_aryAble Integer or instance N_aryAble N_ary (to change one base to another), but I ran into a problem with

instance N_aryAble Int where
  int ~> base = fromIntegral int ~> base

Ambiguous type variable ‘a0’ arising from a use of ‘fromIntegral’
prevents the constraint ‘(Num a0)’ from being solved.
...

Ambiguous type variable ‘a0’ arising from a use of ‘~>’
prevents the constraint ‘(N_aryAble a0)’ from being solved.
...

Type signatures within instance declarations are not allowed without a special setting.

instance N_aryAble Int where
  (~>) :: Int -> Int -> N_ary
  int ~> base = fromIntegral int ~> base

 Illegal type signature in instance declaration:
    (~>) :: Int -> Int -> N_ary
  (Use InstanceSigs to allow this)

The following works.

instance N_aryAble Int where
  int ~> base = fromIntegral int + (0::Integer) ~> base

> (5::Int) ~> 2  ==> N_ary 1 "101" 2

But that seems ugly and ad hoc . Is there a better way?

Thanks.

You can provide a type annotation to the fromIntegral call, so to make it non ambiguous.

instance N_aryAble Int where
  int ~> base = (fromIntegral int :: Integer) ~> base

The problem is not that the compiler can't deduce what from to convert the type from. That could be fixed with a signature for that particular instance method, which BTW you could write like

instance N_aryAble Int where
  (~>) = (~~>)
   where (~~>) :: Int -> Int -> N_ary
         int ~~> base = fromIntegral int ~> base

But that information is already clear from the class method signature, so it won't help you.

No, the problem is that you don't specify what type to convert to , and because the argument to ~> is again polymorphic the compiler has nothing else to infer it from. This could as well convert Int to Int , causing an infinite recursion loop because you end up with the same ~> instantiation you're trying to define!

You can either clarify this with a signature to the result of fromIntegral as shown by chi , or you can simply use the to- -version of the conversion function that's monomorphic with an Integer result:

instance N_aryAble Int where
  int ~> base = toInteger int ~> base

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