2

나는 이전의 추출 기능을 MonadTrans 과부하하려고합니다. 나의 현재 시도는 관련 유형 Result의 인스턴스로 m 내부-모나드를 배치했다 :하스켈의 변수 관련 유형/데이터 유형

class (Monad Result 
     , MonadTrans m 
     , MonadReader prefix m 
     ,) => FooReader prefix m where 
    type Result 
    runFooReader :: forall b. m b -> prefix -> Result b 

instance Monad m => FooReader prefix (ReaderT prefix m) 
    type Result = m -- This is there the error is thrown 
    runFooReader = runReaderT 

Foo이 재미있는 모양이다 유일한 이유는 MonadTransMonadReader 제한 때문이다. 기본적으로 이것은 연관된 모든 유형 인스턴스가 단조 형이되도록합니다 (올바른?).

그때, 그것을 재 설계 단순히 다형성 vairable Result을 생각

:

... 
class FooReader prefix m where 
    runFooReader :: forall b result. m b -> prefix -> result b 

...하지만 그 경우에, 유형 resultw (이 예를 들어, mReaderT prefix w 인 경우) 을 통합하지 않습니다. 이걸 만들 수있는 방법이 있습니까 result varialbe/idea 다형성, 아직 결정할 수 있습니까?

class (Monad Result 
     , MonadTrans m 
     , MonadReader prefix m 
    ) => FooReader prefix m where 
    type Result :: * -> * 
    runFooReader :: forall b. m b -> prefix -> Result b 

instance Monad m => FooReader prefix (ReaderT prefix m) where 
    type Result = m -- Again, error triggered here 
    runFooReader = runReaderT 

그리고 더 흥미로운 오류 :

The RHS of an associated type declaration mentions type variable `m' 
    All such variables must be bound on the LHS 

the GHC docs에 확장됩니다

+1

시도'클래스 FooReader 접두사 m : 여기

컴파일 뭔가 접두사 -> m', mtl과 같은 일을합니다 (그리고 아마 당신이 원하는 것입니다). 만약 내가 올바르게 이해한다면, 당신은 "runStateT','runReaderT','runReaderT '와 같이 행동하는 임의의"모나드 변압기 스택 "과"unwraps "을 취하는 함수"run "을 작성하고 싶습니다. runStateT' 등이 있습니다. 이 작업을 수행하는 일부 코드를 작성한 것을 기억합니다. 작동하지만 형식 오류는 상당 부분 끔찍한 것이 었습니다. 따라서 자주 발생하는 특정 유형의 함수를 정의하는 것만으로도 충분합니다. – user2407038

답변

4

구문 오류를 정리하고 Result에 일종의 주석을 추가, 우리는이 얻을

The visibility of class parameters in the right-hand side of associated family instances depends solely on the parameters of the family. As an example, consider the simple class declaration

class C a b where 
    data T a 

Only one of the two class parameters is a parameter to the data family. Hence, the following instance declaration is invalid:

instance C [c] d where 
    data T [c] = MkT (c, d) -- WRONG!! 'd' is not in scope 

Here, the right-hand side of the data instance mentions the type variable d that does not occur in its left-hand side. We cannot admit such data instances as they would compromise type safety.

"타협하지 않는 유형 안전"po int,이 GHCi 세션을 상상해보십시오 :

> :kind! Result 
Result :: * -> * 
= {- ... well, what? m? -} 

아마도 을 의미 할 것입니다.

아직 오류가 있습니다. 특히, m의 종류는 일관성이 없습니다. MonadTrans에는 (* -> *) -> * -> *의 매개 변수가 필요하지만 MonadReader의 두 번째 매개 변수에는 * -> *이 필요합니다. 왜 MonadTrans이 필요한지 알 수 없습니다.

"모든 관련 유형 인스턴스가 단 일치형이어야합니다."라는 의미를 이해하지 못합니다. 작성한 Result 유형은 매개 변수가 없기 때문에 유형 함수가 아닙니다. LHS에는 타입 변수가 없습니다. |

class (Monad (Result m) 
     , MonadReader prefix m 
    ) => FooReader prefix (m :: * -> *) where 
    type Result m :: * -> * 
    runFooReader :: forall b. m b -> prefix -> Result m b 

instance Monad m => FooReader prefix (ReaderT prefix m) where 
    type Result (ReaderT prefix m) = m 
    runFooReader = runReaderT 

 

> :kind! Result (ReaderT Int IO) 
Result (ReaderT Int IO) :: * -> * 
= IO 
+0

"MonadTrans"수퍼 클래스는 실수 였지만, 정확히 내가 필요로하는 것이었다. 진심으로 감사드립니다 :) –