2017-12-20 7 views
0

기본적으로 Either와 Maybe 중첩 된 형식의 Functor 인스턴스에 문제가 있습니다.Either와 Maybe로 구성된 Type의 Functor 인스턴스를 만드는 방법

data Tuple a b = Tuple a b 
data Primitive = String String | Boolean Boolean | Number Number | Null 
data JsonValue = Object (Map String JsonValue) | Array (List JsonValue) | Primitive 
type Path = List String 
data JsonGraphValue = JsonGraphObject (Map String JsonGraphValue) | Atom JsonValue | Ref Path | Error JsonValue | JsonPrimitive Primitive 

newtype JsonGraphRecResult a = JsonGraphRecResult (Either String (Tuple (Maybe a) (List Path))) 
instance jsonGraphRecResultFunctor :: Functor JsonGraphRecResult where 
    map f (JsonGraphRecResult (Right (Tuple (Just value) paths))) = JsonGraphRecResult (Right (Tuple (Just (f value)) paths)) 
    map f value = value 

위 코드의 끝에있는 "value"단어를 가리키는 다음 오류가 발생합니다. JsonGraphRecResult 잘 컴파일 다음 ㅋ 유형에서 어떤 다른 이유

Could not match type 

    a1 

    with type 

    b0 


while trying to match type JsonGraphRecResult a1 
    with type JsonGraphRecResult b0 
while checking that expression value 
    has type JsonGraphRecResult b0 
in value declaration jsonGraphRecResultFunctor 

where b0 is a rigid type variable 
     a1 is a rigid type variable 

그것은 내게 분명하지 않다 :

newtype Blah a = Blah (Maybe a) 
instance blahFunctor :: Functor Blah where 
    map f (Blah (Just x)) = Blah (Just (f x)) 
    map f value = value 

다음 gist 위해 "PureScript 시도"온라인 REPL에 직접 붙여 넣을 수 있습니다 오류를 복제합니다.

답변

0

문제를 파악했습니다. 입력 값이 올바른 유형이 아니기 때문에 어느 것이 든 왼쪽 인 경우지도 함수의 입력 값을 반환 할 수 없습니다. 다음은 간단한 문제 버전입니다.

-- This is wrong because value is a Functor a, whereas map must return Functor b 
map [email protected] f = value 

-- This is right, because even though both sides are Nothing, the right-hand side is a Maybe b vs. Maybe a 
map Nothing f = Nothing 
0

유형에 대해 Functor 인스턴스를 파생시킬 수 있어야합니다. 당신이 당신의 마지막 유형의 인스턴스를 유도하지만 그 전에 당신은 (;-)하거나 Data.Tuple에서 Tuple를 사용)하여 Tuple 유형을 도출해야

data Tuple a b = Tuple a b 
derive instance functorTuple :: Functor (Tuple a) 

당신이 Functor 인스턴스를 볼 수있는 유형에 대해서만 정의 할 수 있습니다 종류 * -> *이므로이 경우 에 "마지막 위치"를 차지하는 유형 인 map을 입력 할 수 있습니다. trypurescript.org

newtype JsonGraphRecResult a = 
    JsonGraphRecResult (Either String (Tuple (List Path) (Maybe a))) 
derive instance functorJsonGraphRecResult :: Functor JsonGraphRecResult 

Here는 관련이 대화 형 조각 그래서 당신은 재생할 수 있습니다 : 당신의 JsonGraphRecResult 당신이 "마지막 위치"요구 사항을 만족 Tuple 내부의에서 유형의 순서를 변경해야 할에 대한 인스턴스를 도출하기 위해

이 구현으로.

이 유도하는 메커니즘을 사용할 수있는 더 많은 종류의 클래스가 있습니다 Ord, Eq, Generic, Newtype ...

Purescript에 추가 유도하는 옵션을 가지고 이러한 맥락에서 지적 가치가있다 이것은 "newtype derived"입니다.

derive newtype instance someClassMyType :: SomeClass MyType 

뉴 타입의 유도하는 주어진 newtype은 내부 형은 이미 인스턴스를 정의한 클래스의 인스턴스를 유도하기위한 newtype "래퍼"에 사용됩니다 : 예를 들어, - 그것은 derivenewtype 키워드를 포함하고 있기 때문에 구문은 조금 다르다입니다. 즉, newtype T = T a이 있으면 a에 인스턴스가있는 모든 클래스에 대해 T에 대한 newtype 인스턴스를 파생시킬 수 있습니다.

또 다른 전략이 있습니다. Data.Generic.Rep의 일부 유형 클래스에 정의 된 메소드의 일반 구현을 사용할 수도 있습니다. 이러한 구현은 Generic 클래스의 인스턴스 인 유형에 사용할 수 있습니다.

https://github.com/paf31/24-days-of-purescript-2016

:하지만 당신은 필의에서 "24 일 Purescript의"시리즈를 부여에 대한 자세한 정보를 찾을 수있는 또 다른 이야기 ;-)

전체입니다