使用默认值映射 Maybes

Mapping Maybes with defaults

我是 Elm 和 fp 的新手,所以我正在尝试解决这个问题

我正在尝试解码 Json,其中可能有 2 个可选字段 "username" 和 "password"

我成功解码结构为如下类型

type alias Req = 
    { ...
    , username : Maybe String
    , password: Maybe String
    }

我还有其他类型

type alias BA = 
     { username : String
     , password : String
     }

type alias sBA = Maybe BA

现在我想要一个函数 getsBa 以便我可以执行以下操作

getsBA : Req -> sBA
...

a : Req
a = { ...
     , username = Just "test"
     , password = Nothing
     }

getsBA a == Just { username = "test", password = "" }

b = { ...
     , username = Nothing
     , password = Nothing
     }
 getsBA b = Nothing

c : Req
c = { ...
     , username = Nothing
     , password = Just "123"
     }

getsBA a == Just { username = "", password = "123" }


d : Req
d = { ...
     , username = Just "test"
     , password = Just "123"
     }

getsBA a == Just { username = "test", password = "123" }

我如何从 FP 的角度考虑这样的解决方案?

type alias Creds = (Maybe String, Maybe String)
f :: Req -> Creds
f r = (r.username, r.password)

g :: Creds -> sBA
g c = 
  case c of
    (Nothing, Nothing) -> Nothing
    (Nothing, Just p) -> Just {username = "", password = p}
    (Just u, Nothing) -> Just {username = u, password = ""}
    (Just u, Just p) -> Just {username = u, password = p}

getsBA = g << f

f 是字段提取器,g 操作这些值,getsBA 是这两者的组合(提取字段然后操作它们)。

这是@duggi 答案的替代方法,它使用 Maybe.withDefault 来减少代码中的重复:

getsBA : Req -> SBA
getsBA { username, password } =
    case ( username, password ) of
        ( Nothing, Nothing ) ->
            Nothing

        _ ->
            Just <| BA (Maybe.withDefault "" username) (Maybe.withDefault "" password)