【发布时间】:2017-11-22 18:44:33
【问题描述】:
几天前,我 asked a question 关于在 free-monads 的上下文中注入函子。那里建议的解决方案基于Data Types à la Carte,使用一个表示函子之间的一种包含关系的类。
-- | Class that represents the relationship between a functor 'sup' containing
-- a functor 'sub'.
class (Functor sub, Functor sup) => sub :-<: sup where
inj :: sub a -> sup a
-- | A functor contains itself.
instance Functor f => f :-<: f where
inj = id
-- | A functor is contained in the sum of that functor with another.
instance (Functor f, Functor g) => f :-<: (Sum f g) where
inj = InL
-- | If a functor 'f' is contained in a functor 'g', then f is contained in the
-- sum of a third functor, say 'h', with 'g'.
instance (Functor f, Functor g, Functor h, f :-<: g) => f :-<: (Sum h g) where
inj = InR . inj
现在考虑以下数据类型:
type WeatherData = String
data WeatherServiceF a = Fetch (WeatherData -> a) deriving (Functor)
data StorageF a = Store WeatherData a deriving (Functor)
还有如下类型的函数
fetch :: (WeatherServiceF :-<: g) => Free g WeatherData
其中Free 来自Control.Monad.Free 模块。
那么如果我尝试使用这个功能如下:
reportWeather :: Free (Sum WeatherServiceF StorageF) ()
reportWeather = do
_ <- fetch
return ()
我得到一个重叠实例错误,说:
• Overlapping instances for WeatherServiceF
:-<: Sum WeatherServiceF StorageF
arising from a use of ‘fetch’
Matching instances:
two instances involving out-of-scope types
instance (Functor f, Functor g) => f :-<: Sum f g
instance (Functor f, Functor g, Functor h, f :-<: g) =>
f :-<: Sum h g
现在,我知道第一个是有效实例,但为什么第二个也被视为有效实例?如果我在第二种情况下实例化变量,我会得到 p>
instance ( Functor WeatherServiceF
, Functor StorageF
, Functor WeatherServiceF
, WeatherServiceF :-<: StorageF
) => WeatherServiceF :-<: Sum WeatherServiceF g
这不应该是一个实例,因为WeatherServiceF :-<: StorageF 不是真的。为什么 GHC 会推断出这样一个实例?
我启用了以下实例:
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeOperators #-}
【问题讨论】:
标签: haskell typeclass overlapping-instances