在将类型创建为Eq的实例时,==的模糊出现

qed*_*qed 3 haskell operator-overloading

了解你是一个很好的Haskell:

class Eq1 a where
    (==) :: a -> a -> Bool
    (/=) :: a -> a -> Bool
    x == y = not (x /= y)
    x /= y = not (x == y)

data TrafficLight = Red | Yellow | Green

instance Eq1 TrafficLight where
    Red == Red = True
    Green == Green = True
    Yellow == Yellow = True
    _ == _ = False
Run Code Online (Sandbox Code Playgroud)

当我加载它时ghci,我收到一个错误:

baby.hs:213:9:
    Ambiguous occurrence ‘==’
    It could refer to either ‘Main.==’, defined at baby.hs:225:5
                          or ‘Prelude.==’,
                             imported from ‘Prelude’ at baby.hs:1:1
                             (and originally defined in ‘GHC.Classes’)
Run Code Online (Sandbox Code Playgroud)

据我了解,==这里有具体的Trafficlight类型.歧义在哪里,这里?

Zet*_*eta 10

问题实际上在于class Eq1,而不是instance Eq1 Trafficlight:

class Eq1 a where
    (==) :: a -> a -> Bool
    (/=) :: a -> a -> Bool
    x == y = not (x /= y) -- which (/=) ?
    x /= y = not (x == y) -- which (==) ?
Run Code Online (Sandbox Code Playgroud)

那时候还不清楚你是否想要使用Prelude.==Main.==.你需要说清楚:

class Eq1 a where
    (==) :: a -> a -> Bool
    (/=) :: a -> a -> Bool
    x == y = not (x Main./= y)
    x /= y = not (x Main.== y)
Run Code Online (Sandbox Code Playgroud)

现在instance Eq1 Trafficlight将工作,因为你真的定义(==)(/=)您的Eq1实例.但是,请记住,Red == Yellow这仍然是模棱两可的,因为实际上有两个(==)并且(/=)在手边.为了解决这个问题,您需要将所有调用前缀添加到==/=.

更好地为您的运营商使用其他名称:

class Eq1 a where
   (===), (=/=) :: a -> a -> Bool
   x === y = not $ x =/= y
   x =/= y = not $ x === y
Run Code Online (Sandbox Code Playgroud)