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.