저는 현재 haskell에 서버를 만들고 언어에 대한 초보자로서 새로운 접근법을 시도하고 싶습니다. 아이디어는 기본 모나드에 대해 알지 못하는 채로 작동하는하스켈에서 타입 시스템과 싸우지 않고 모나드를 추상화하는 방법은 무엇입니까?
isGetRequest :: (SupportsRequests m r) => m Bool
isGetRequest = do
method <- liftRequests $ requestMethod
return $ method == GET
class (Monad m, RequestSupport r) => SupportsRequests m r | m -> r where
liftRequests :: r a -> m a
class (Monad r) => RequestSupport r where
requestMethod :: r Method
과 같은 라이브러리 메소드를 작성할 수 있다는 것입니다. 물론이 예제에서는 (RequestSupport r) 모나드에서 isGetRequest를 직접 작동시키는 것으로 충분했지만 내 라이브러리가 모나드에 둘 이상의 제약 조건을 가질 수 있다는 아이디어가 있습니다. 그러나 나는 같은 모듈에있는 모든 다른 관심사를 구현하고 다른 모듈 (고아 인스턴스!)에 퍼트 리는 것을 원하지 않습니다. 이것이 m 모나드가 Supports*
클래스만을 구현하여 실제 문제를 다른 모나드에 위임 한 이유입니다.
위의 코드는 완벽하게 작동합니다 (GHC의 일부 언어 확장 포함). 아니 내가 얻을 오류
class (Monad m, CRUDSupport c a) => SupportsCRUD m c a | m a -> c where
liftCRUD :: c x -> m x
class (Monad c) => CRUDSupport c a | c -> a where
list :: c [a] -- List all entities of type a
: 불행하게도, 나는 CRUD 몇 가지 문제를 가지고 문제를 (읽기 업데이트 삭제 만들기 없음)
Could not deduce (SupportsCRUD m c a0) from the context [...]
The type variable 'a0' is ambiguous [...]
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
When checking the class method: liftCRUD [...]
이 유형 검사처럼 보인다
좋아하지 않습니다 그a
매개 변수 리프트 CRUD의 서명에서 직접 발생하지 않습니다.
a
은 기능 종속성에서 파생 될 수 없으므로 이해할 수 있습니다.
내 뇌의 유형 검사기는 나중에 CRUD에 관한 일부 메소드가 라이브러리 메소드에서 실행될 때 AllowAmbiguousTypes를 사용하여 a
유형을 유추하는 데 문제가 없어야한다고 알려줍니다. 불행하게도, GHC 예를 들어,이 추론 단계를 할 수없는 것 같다
bookAvailable :: (SupportsCRUD m c Book) => m Bool
bookAvailable = do
books <- liftCRUD (list :: c [Book]) -- I use ScopedTypeVariables
case books of
[] -> return False
_ -> return True
아직도 컴파일러를 추론 할 수없는 나는 것 같다
Could not deduce (SupportsCRUD m c0 a1) arising from a use of 'liftCRUD' [...]
The type variables c0, a1 are ambiguous [...]
를 얻을 수 있습니다. 이 문제를 해결할 방법이 있습니까? 아니면 적어도 컴파일러가 무엇을 추론 할 수 있는지 이해하는 방법?
최고 감사합니다, bloxx
'SupportsCRUD' 클래스 선언은 'm','c' 및'a'의 세 가지 유형 변수를 포함합니다. 귀하의 예제에서이 세 가지 변수에 대해 컴파일러가 예상하는 값이 무엇이고 그 이유는 무엇이라고 말할 수 있습니까? –
'm a -> c'라는 펀드가 의도 한 바는 무엇입니까? 이것이 의미하는 바는 "'c '의 선택은 타입 검사기가'm'과'a'만으로 인스턴스를 선택할 수 있다는 특수한 타입 인'm'과'a'에 의해 유일하게 결정됩니다. 상황에 따라 달라지며 'c'는 인스턴스 헤드에 넣은 것과 같습니다. – jberryman
@jberryman 실제로 컴파일러에게 모나드와 "CRUD 엔티티"a에 대해 유형 검사기가 고유 한 모나드 C (CRUD 연산을 지원하는 하나의 고유 한 모나드)를 선택할 수 있도록 알려줍니다. – bloxx