2016-11-27 15 views
2

다음 코드에서 알 수 있듯이 UserAlias를 디코딩하기가 쉽지만 UserType을 디코드하려고 시도하면 즉 D.map2 UserAliasD.map2 UserType으로 바꿉니다. 컴파일러가 소리내어 울립니다. 이 컴파일러 오류를 어떻게 수정합니까?Elm : Json이 단일 TypeConstructor로 Union 형식을 디코딩하는 방법은 무엇입니까?

import Json.Decode as D 
import Html exposing (..) 
import Result as R 

type UserType = UserType {name:String, age:Int} 

type alias UserAlias = {name:String, age:Int} 


userDecoder = D.map2 UserAlias 
       (D.field "name" D.string) 
       (D.field "age" D.int) 


decodeUser json = D.decodeString userDecoder json 


json = """ 
    { "name": "Bob", "age": 40 } 
""" 


main = div [] [(text << toString << decodeUser) json] 

위의 코드는 정상적으로 작동합니다. 이제 D.map2 UserType

그리고 컴파일러 D.map2 UserAlias을 대체하는 것은 내가이 오류를 수정하려면 어떻게

Detected errors in 1 module. 
==================================== ERRORS ==================================== 



-- TYPE MISMATCH --------------------------------------------------------------- 

The 2nd argument to function `map2` is causing a mismatch. 

13|    D.map2 UserType 
14|>    (D.field "name" D.string) 
15|     (D.field "age" D.int) 

Function `map2` is expecting the 2nd argument to be: 

    D.Decoder { age : Int, name : String } 

But it is: 

    D.Decoder String 

Hint: I always figure out the type of arguments from left to right. If an 
argument is acceptable when I check it, I assume it is "correct" in subsequent 
checks. So the problem may actually be in how previous arguments interact with 
the 2nd. 



-- TYPE MISMATCH --------------------------------------------------------------- 

The 1st argument to function `map2` is causing a mismatch. 

13|>    D.map2 UserType 
14|     (D.field "name" D.string) 
15|     (D.field "age" D.int) 

Function `map2` is expecting the 1st argument to be: 

    { age : Int, name : String } -> b -> UserType 

But it is: 

    { age : Int, name : String } -> UserType 

Hint: It looks like a function needs 1 more argument. 

, 도와주세요 울고!

기본적으로 나는 내부 레코드 구조를 숨길 수 있고 공용 API를 손상시키지 않고 리팩터링 할 수 있도록 사용자 별 UserType 만 사용하고자한다.

감사합니다.

답변

3

UserType 생성자는 UserAlias의 단일 매개 변수를, 그래서 우리는 간단하게 다음과 같이 UserTypeUserAlias 값을 적용하려면 기존 디코더 내부 Json.Decode.map을 사용하고 디코더를 구성 할 수 있습니다 :

userDecoder : D.Decoder UserType 
userDecoder = D.map2 UserAlias 
       (D.field "name" D.string) 
       (D.field "age" D.int) 
       |> D.map UserType 
+0

덕분에 많이, 당신은 보호기 항상 생명이다 : 이제 마지막으로 유형을 사용할 수 있습니다 D 구현 구조를 숨기는 생성자입니다. – Jigar

+0

하지만 여전히 형식 별칭을 사용합니다. OP는 형식 별칭이없는 해결책을 찾고있었습니다 –

3

약간 더 차드의 대답보다 직접적인 방법은 map2 함수에서 이렇게하는 것입니다.

userDecoder : D.Decoder UserType 
userDecoder = D.map2 (\name age -> UserType <| UserAlias name age) 
       (D.field "name" D.string) 
       (D.field "age" D.int) 

두 번째 map의 패턴 일치를 피할 수 있습니다. 그것은 아마 여기에서 성과의 점에서 당신에게 다량을 사지 않을 것입니다! 당신이 좀 더 간결하고있는 것 같은 느낌이 경우

, 이것은 또한 pointfree 스타일로 작성 할 수 있습니다

userDecoder = D.map2 (((<<) UserType) << UserAlias) 
       (D.field "name" D.string) 
       (D.field "age" D.int) 
+0

감사합니다.이 API의 작동 방식을 이해하는 데 도움이되므로 정말 감사드립니다. 바라건대, 나는 내 코드에서 그런 패턴을 배우고 받아 들일 수있을 것이다. 실용적인 목적으로 차드의 답변을 사용 하겠지만;) – Jigar