전 몇 달 전 자유 모나크 컨텍스트에서 펑터 주입에 대해 I asked a question에 대해 설명합니다. Data Types à la Carte에 기반한 해결책은 펑터 (functor) 간의 일종의 포함 관계를 나타내는 클래스를 사용합니다. Free
가 Control.Monad.Free
모듈에서 오는 경우이 두 인스턴스가 겹치는 방법 (범위를 벗어난 유형 포함)
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
와 기능 :
-- | 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
는 이제 다음과 같은 데이터 유형을 고려하십시오. 나는이 기능을 사용하려고하면
그런 다음 다음과 같이 내가 처음이 유효한 인스턴스 인 이해,
• 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
을 지금 :
reportWeather :: Free (Sum WeatherServiceF StorageF)()
reportWeather = do
_ <- fetch
return()
내 말은, 중복-경우 오류가 발생합니다 ,하지만 두 번째 이유가 유효한 인스턴스로 간주되는 이유는 무엇입니까? 내가 두 번째 경우에서 변수를 인스턴스화하면 나는 그렇지 사실 WeatherServiceF :-<: StorageF
그 때문에 인스턴스 안
instance (Functor WeatherServiceF
, Functor StorageF
, Functor WeatherServiceF
, WeatherServiceF :-<: StorageF
) => WeatherServiceF :-<: Sum WeatherServiceF g
을 얻을 것입니다. GHC는 왜 그러한 사례를 추론합니까?
나는 다음과 같은 경우를 사용할 수 있습니다
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeOperators #-}
우수. 나는 그것에 대해 몰랐다. 나는이 질문에있는 예제에서이 중첩 인스턴스 오류를 피할 수있는 이유가 무엇입니까? –
물론 'OverlappingInstances'에 의지하지 않고 :) –