如何在elm-core中的Json.Decoder中从String转换为Int> 5.0.0

时间:2016-11-22 07:30:15

标签: json elm

这对于this question来说是理想的,除了elm从那以后发生了变化,所以答案不再有效(特别是不再有Decode.customDecoder个对象。)

你如何在elm-core>中做同样的事情5.0.0?

6 个答案:

答案 0 :(得分:6)

一种方法(从Elm 0.18和核心5.0开始)将是这样的:

df <- read.table(text='product share_per return_per min_share_per
                 prod1   0.5       0.1        0.2
                 prod2   0.2       0.4        0.1
                 prod3   0.2       0.05       0.0
                 prod4   0.1       0.04       0.0
                 prod5   0.0       0.3        0.0', header=TRUE)

ret <- df$return_per

fn <- function(sp) sum(ret*sp) # objective

Amat <- rbind(diag(nrow(df)), diag(-1,nrow(df)), rep(-1,nrow(df))) # constraints
bvec  <- c(df$min_share_per, rep(-1, nrow(df)), -1)                # sp_j >= min_share_per,  
                                                                   # sp_j <= 1 and 
                                                                   # sum_j sp_j <= 1
init <- c(0.5,0.2,0.2,0.05,0.01) # making sure that the initial value is in the feasible region

sol <- constrOptim(init, fn, NULL, ui = Amat, ci = bvec, control=list(fnscale=-1)) # maximize
round(sol$par, 2)
# [1] 0.2 0.8 0.0 0.0 0.0

标准库中的stringIntDecoder : Decoder Int stringIntDecoder = Json.Decode.map (\str -> String.toInt (str) |> Result.withDefault 0) Json.Decode.string 函数接受一个字符串并尝试将其转换为整数,并返回一个Result。 String.toInt执行其名称所暗示的内容 - 您为其提供了一些默认值和结果,如果结果为Result.withDefault,则会得到Ok x但如果它是x则会得到你提供的默认值,这里是0.如果你愿意,可以自己编写一个函数来自己处理一个Result,而不是传递那个函数。

答案 1 :(得分:3)

您可以使用succeed中的failJson.Decode创建自己的自定义解码器。我改变了下面的参数顺序,使其可以链接。

修改:从结果问题中分离出解码器问题。

import Json.Decode as Json
import Result


-- // This is a Result helper function that could be used elsewhere.
-- // Currently, there is no Result.either in Elm core.
eitherR : (x -> b) -> (a -> b) -> Result x a -> b
eitherR fErr fOk result =
    case result of
        Err x ->
            fErr x

        Ok a ->
            fOk a


customDecoder : (a -> Result String b) -> Json.Decoder a -> Json.Decoder b
customDecoder fResult decoder =
    decoder |> Json.andThen (fResult >> eitherR Json.fail Json.succeed)

将此问题插入相关问题......

let number =
    Json.oneOf [ Json.int, Json.string |> customDecoder String.toInt ]

这是另一个使用示例。这是onChange的版本,它将值转换为整数。当您知道选项值是Int。

时,对select主要有用
import Html
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import String


onChangeInt : (Int -> msg) -> Attribute msg
onChangeInt fMsg =
    on "change" (targetValue |> customDecoder String.toInt |> Json.map fMsg)

请注意,targetValue在Html.Events模块中定义:

targetValue : Decoder String

答案 2 :(得分:1)

使用parseInt解码器(source):

decodeString parseInt """ "123" """

查看有关自定义解码器的tutorial,例如日期。重用fromResult方法。

了解parseInt函数中使用的function composition (<<)

答案 3 :(得分:0)

鉴于在对另一个答案的评论中,你表明需要接受可能的失败,你可以使用一个Maybe。

stringIntDecoder : Decoder (Maybe Int)
stringIntDecoder =
    Json.Decode.map (String.toInt >> Result.toMaybe) Json.Decode.string

或者

stringIntDecoder : Decoder (Result String Int)
stringIntDecoder =
    Json.Decode.map (String.toInt) Json.Decode.string

答案 4 :(得分:0)

对于使用targetValue文档的Elm 0.19,代码变为:

import Html.Events
import Json.Decode

onIntInput : (Int -> msg) -> Attribute msg
onIntInput tagger =
    Html.Events.stopPropagationOn "input" <|
        Json.Decode.map alwaysStop (Json.Decode.map tagger targetIntValue)

targetIntValue : Decoder Int
targetIntValue =
  Json.Decode.at ["target", "value"] Json.Decode.string |> Json.Decode.andThen (\value ->
    case String.toInt value of
      Just number -> Json.Decode.succeed number
      Nothing -> Json.Decode.fail "not a number")

alwaysStop : a -> (a, Bool)
alwaysStop x =
  (x, True)

,然后可以在使用onInput的地方使用onIntInput。

答案 5 :(得分:0)

这是一种避免选择粗略默认值的解决方案:

import Json.Decode as Decode exposing (Decoder)

decodeIntString : Decoder (Maybe Int)
decodeIntString =
    Decode.map String.toInt Decode.string


decodeMaybeFail : Maybe a -> Decoder a
decodeMaybeFail val =
    case val of
        Just a ->
            Decode.succeed a

        Nothing ->
            Decode.fail "'Nothing' value can't be decoded"

然后将其与

一起使用
Decode.andThen decodeMaybeFail decodeIntString

(类型为Decoder Int,因此您可以像使用Decode.int一样使用它)

乍一看并不明显,但它说明了如何将此问题分解为简单的小步骤。

我认为函数decodeMaybeFail : Maybe a -> Decoder a应该在标准Json.Decode模块中。