Opened 2 years ago

Closed 2 years ago

#13946 closed feature request (invalid)

自動選擇實例

Reported by: zaoqi Owned by:
Priority: normal Milestone:
Component: Compiler Version: 8.0.2
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description (last modified by zaoqi)

{-# LANGUAGE MultiParamTypeClasses #-}

class B a b where
    b :: a -> b

instance B Int Char where
    b = error "B Int Char"

instance B Int () where
    b = error "B Int ()"
*Main> :t (b undefined)::Char

<interactive>:1:2: error:
    • Ambiguous type variable ‘a0’ arising from a use of ‘b’
      prevents the constraint ‘(B a0 Char)’ from being solved.
      Probable fix: use a type annotation to specify what ‘a0’ should be.
      These potential instance exist:
        instance [safe] B Int Char -- Defined at t.hs:6:10
    • In the expression: (b undefined) :: Char

怎麼讓GHC在這種情況下自動選擇任意一個實例

[WARING]Google Translate

How to make GHC automatically select any instance in this case

Change History (2)

comment:1 Changed 2 years ago by zaoqi

Description: modified (diff)

comment:2 Changed 2 years ago by RyanGlScott

Resolution: invalid
Status: newclosed

This is behaving as expected. The issue is that when you type (b undefined) :: Char, GHC attempts to look for a B a Char instance. But a is underdetermined, so GHC cannot successfully find an instance.

What you can do is use FunctionalDependencies to inform GHC that b uniquely determines a. That is, you can do this:

{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}

class B a b | b -> a where
    b :: a -> b

instance B Int Char where
    b = error "B Int Char"

instance B Int () where
    b = error "B Int ()"

Note the use of | b -> a in the class declaration for B. This is the notation used to express that b uniquely determines a. Now, if you try this:

> :t (b undefined) :: Char
(b undefined) :: Char :: Char

It works, since when GHC tries to find a B a Char instance, it knows that Char uniquely determines what a should be (in this case, Int), so it finds the B Int Char and proceeds.

I'm going to close this as invalid - please reopen if this didn't answer your question in a satisfactory way.

Note: See TracTickets for help on using tickets.