gpt4 book ai didi

purescript - 从不一致的 JavaScript 对象创建 PureScript 记录

转载 作者:行者123 更新时间:2023-12-04 01:59:06 25 4
gpt4 key购买 nike

假设我的 PureScript 代码中有以下类型的用户记录:

{ id        :: Number
, username :: String
, email :: Maybe String
, isActive :: Boolean
}

CommonJS 模块派生自 PureScript 代码。导出的用户相关函数将从外部 JavaScript 代码调用。

在 JavaScript 代码中,“用户”可以表示为:
var alice = {id: 123, username: 'alice', email: 'alice@example.com', isActive: true};
email可能是 null :
var alice = {id: 123, username: 'alice', email: null, isActive: true};
email可以省略:
var alice = {id: 123, username: 'alice', isActive: true};
isActive可以省略,在这种情况下假定 true :
var alice = {id: 123, username: 'alice'};
id不幸的是,有时是一个数字字符串:
var alice = {id: '123', username: 'alice'};

上面的五种 JavaScript 表示是等价的,并且应该产生等价的 PureScript 记录。

如何编写一个接受 JavaScript 对象并返回用户记录的函数? 它将使用 null/省略的可选字段的默认值,强制字符串 id到一个数字,如果缺少必填字段或值的类型错误,则抛出。

我可以看到的两种方法是在 PureScript 模块中使用 FFI 或在外部 JavaScript 代码中定义转换函数。后者似乎毛茸茸的:
function convert(user) {
var rec = {};
if (user.email == null) {
rec.email = PS.Data_Maybe.Nothing.value;
} else if (typeof user.email == 'string') {
rec.email = PS.Data_Maybe.Just.create(user.email);
} else {
throw new TypeError('"email" must be a string or null');
}
// ...
}

我不确定 FFI 版本将如何工作。我还没有处理过效果。

很抱歉,这个问题不是很清楚。我还没有足够的了解来确切地知道我想知道什么。

最佳答案

我已经提出了一个解决方案。我确信可以改进很多,例如更改 toUser 的类型至Json -> Either String User并保留错误信息。如果您能看到可以改进此代码的任何方法,请发表评论。 :)

此解决方案使用 PureScript-Argonaut除了几个核心模块。

module Main
( User()
, toEmail
, toId
, toIsActive
, toUser
, toUsername
) where

import Control.Alt ((<|>))
import Data.Argonaut ((.?), toObject)
import Data.Argonaut.Core (JNumber(), JObject(), Json())
import Data.Either (Either(..), either)
import Data.Maybe (Maybe(..))
import Global (isNaN, readFloat)

type User = { id :: Number
, username :: String
, email :: Maybe String
, isActive :: Boolean
}

hush :: forall a b. Either a b -> Maybe b
hush = either (const Nothing) Just

toId :: JObject -> Maybe Number
toId obj = fromNumber <|> fromString
where
fromNumber = (hush $ obj .? "id")
fromString = (hush $ obj .? "id") >>= \s ->
let id = readFloat s in if isNaN id then Nothing else Just id

toUsername :: JObject -> Maybe String
toUsername obj = hush $ obj .? "username"

toEmail :: JObject -> Maybe String
toEmail obj = hush $ obj .? "email"

toIsActive :: JObject -> Maybe Boolean
toIsActive obj = (hush $ obj .? "isActive") <|> Just true

toUser :: Json -> Maybe User
toUser json = do
obj <- toObject json
id <- toId obj
username <- toUsername obj
isActive <- toIsActive obj
return { id: id
, username: username
, email: toEmail obj
, isActive: isActive
}

更新:我根据 gist 对上面的代码进行了改进。来自本·科莱拉。

关于purescript - 从不一致的 JavaScript 对象创建 PureScript 记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27885264/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com