- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在关注这篇出色的文章的前半部分,但是有一个地方让我陷入困境。 https://jrsinclair.com/articles/2016/marvellously-mysterious-javascript-maybe-monad/
我实现了一个非常相似的Maybe monad,但是我需要传递给map的函数之一是异步的。理想情况下,我可以将.then()和map()结合使用。我想做这样的事情...
const getToken = async (p) => {
let result = utils.Maybe.of(await makeAICCCall(p.aiccsid, p.aiccurl))
.map(parseAuthenticatedUser)
.thenMap(syncUserWithCore) <-- I can't figure this out
.map(managejwt.maketoken)
.value
return result;
}
最佳答案
自然转变
数据容器的嵌套可能会变得凌乱,但是有一种众所周知的技术可以使它们保持扁平-下面的eitherToPromise
被认为是natural transformation –它将Either转换为Promise,从而可以在.then
链中进行扁平化,同时还可以防止您的价值/错误线交叉
注意:您可能想使用makeAICCall
而不是Either
返回Left
(Right
,Maybe
),因为您将能够返回错误消息(而不是Nothing
信息较少)
import { Left, Right, eitherToPromise } from './Either'
const makeAICCall = (...) =>
someCondition
? Left (Error ('error happened'))
: Right (someResult)
const getToken = p =>
makeAICCall (p.aiccsic, p.aiccurl) // => Promise<Either<x>>
.then (eitherToPromise) // => Promise<Promise<x>>
// => auto-flattened to Promise<x>
.then (syncUserWithCore) // => Promise<x>
.then (managejwt.maketoken) // => Promise<x>
Either
实现
// Either.js
export const Left = x =>
({
fold: (f,_) => f (x),
// map: f => Left (x),
// chain: ...,
// ...
})
export const Right = x =>
({
fold: (_,f) => f (x),
// map: f => Right (f (x)),
// chain: ...,
// ...
})
export const eitherToPromise = m =>
m.fold (x => Promise.reject (x), x => Promise.resolve (x))
const someAsyncCall = x =>
new Promise (r => setTimeout (r, 1000, x))
const authenticate = ({user, password}) =>
password !== 'password1'
? Left (Error ('invalid password'))
: Right ({user, id: 123})
const someSyncCall = token =>
Object.assign (token, { now: Date.now () })
const getToken = x =>
someAsyncCall (x)
.then (authenticate)
.then (eitherToPromise)
.then (someSyncCall)
// minimal dependencies
const Left = x =>
({ fold: (f,_) => f (x) })
const Right = x =>
({ fold: (_,f) => f (x) })
const eitherToPromise = m =>
m.fold (x => Promise.reject (x), x => Promise.resolve (x))
// test it
getToken ({user: 'alice', password: 'password1'})
.then (console.log, console.error)
// 1 second later ...
// { user: 'alice', id: 123, now: 1509034652179 }
getToken ({user: 'bob', password: 'password2'})
.then (console.log, console.error)
// 1 second later ...
// Error: invalid password ...
.then
调用–
an answer to your previous question演示了如何以不同的方式表示这样的程序
null
和
undefined
。我们如何以“功能性方式”处理它-这就是您想知道的,对吗?
const Left = x =>
({ fold: (f,_) => f (x) })
const Right = x =>
({ fold: (_,f) => f (x) })
const eitherFromNullable = (x, otherwise = x) =>
x === null ||
x === undefined
? Left (otherwise)
: Right (x)
// !! nullable codomain !!
const find = (f, xs) =>
xs.find (x => f (x))
// example data
const data =
[1,2,3,4,5]
// perform safe lookups by wrapping unsafe find in eitherFromNullable
eitherFromNullable (find (x => x > 3, data))
.fold (console.error, console.log)
// <console.log> 4
eitherFromNullable (find (x => x > 5, data))
.fold (console.error, console.log)
// <console.error> undefined
eitherFromNullable (find (x => x > 5, data), Error (`couldn't find a big number !`))
.fold (console.error, console.log)
// <console.error> Error: couldn't find a big number !
makeAICCall
而不是返回Either,而是返回x或null
eitherFromNullable
对其进行筛选-新代码以粗体显示
const getToken = p =>
makeAICCall (p.aiccsic, p.aiccurl) // => Promise<x?> could be null !!
.then (x => // => Promise<Either<x>>
eitherFromNullable (x, Error ('bad aic call')))
.then (eitherToPromise) // => Promise<Promise<x>>
// => auto-flattened to Promise<x>
.then (syncUserWithCore) // => Promise<x>
.then (managejwt.maketoken) // => Promise<x>
const eitherFromNullable = otherwise => x =>
x == null ? Left (otherwise) : Right (x)
// ooooh, yeah, you like that
makeAICCall (p.aiccsic, p.aiccurl)
.then (eitherFromNullable (Error ('bad aic call')))
.then (eitherToPromise)
.then ...
const eitherFromNullable = (x, otherwise = x) =>
// we consider null and undefined nullable,
// everything else is non-null
x === null ||
x === undefined
? Left (otherwise)
: Right (x)
false
和
0
以及空字符串
''
也是“可空的” –或者,您也可以轻松地确定具有非常特定的适配器
eitherFromNull
,
eitherFromUndefined
,
eitherFromBoolean
等–这是你的程序;由你决定!
// no one wants to do this for every endpoint!
const getUser = id =>
new Promise ((resolve, reject) =>
request ({url: '/users', id}, (err, res) =>
err
? reject (err)
: res.status === 403
? reject (Error ('unauthorized'))
res.body == null ?
? reject (Error ('not found'))
: resolve (User (JSON.parse (res.body)))))
request
,它具有较旧的Node样式的回调接口,我们已经厌倦了将它们包装在Promise中
403
状态响应
null
进行响应;例如
/users/999
,其中
999
是未知的用户ID,不会触发错误,但会获取一个空的响应正文
request
以外的其他方式,但是主管说不。我们希望API端点具有不同的行为,但这是我们无法控制的。尽管如此,编写一个好的程序仍在我们的能力之内
// functional programming is about functions
const safeRequest = (type, ...args) =>
new Promise ((resolve, reject) =>
request[type] (args, (err, res) =>
err
? reject (err)
: res.status === 403
? reject (Error ('unauthorized'))
res.body == null ?
? reject (Error ('not found'))
: resolve (JSON.parse (res.body))))
const getUser = id =>
safeRequest ('get', {url: '/users', id})
const createUser = fields =>
safeRequest ('post', {url: '/users', fields})
const updateUser = (id, fields) =>
safeRequest ('put', {url: '/users', id, fields})
safeRequest
定义的
const promisify = f => (...args) =>
new Promise ((resolve, reject) =>
f (...args, (err, x) =>
err ? reject (err) : resolve (x)))
const promiseFromResponseStatus = res =>
res.status === 403 // or handle other status codes here too !
? Promise.reject (Error ('unauthorized'))
: Promise.resolve (res)
const promiseFromNullableResponse = res =>
res.body == null // or res.body == '', etc
? Promise.reject (Error ('not found'))
: Promise.resolve (res.body)
const safeRequest = (type, ...args) =>
promisify (request [type]) (...args)
.then (promiseFromResponseStatus)
.then (promiseFromNullableResponse)
.then (JSON.parse)
const getUser = id =>
safeRequest ('get', {url: '/users', id})
const createUser ...
....
关于node.js - 有没有一种方法可以编写一个内部带有 promise 的Maybe.map?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46958117/
我正在尝试从一个 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 m
我是 Haskell 的新手,我认为函数 map map和 map.map在 Haskell 中是一样的。 我的终端给了我两种不同的类型, (map.map) :: (a -> b) -> [[a]
我的目标是创建一个 map 的 map ,这样我就可以通过它的键检索外部 map 的信息,然后通过它们的键访问它的“内部” map 。 但是,当我得到每个内部映射时,我最初创建的映射变成了一个对象,我
如何使用 Java8 编写以下代码? for (Entry> entry : data.entrySet()) { Map value = entry.getValue(); if (valu
我有覆盖整个南非的图片。它们为Tiff格式,并已将坐标嵌入其中。我正在尝试拍摄这些图像(大约20张图像),并将它们用作我的iPhone应用程序中的地图叠加层。我的问题在于(准确地)将地图切成图块。 我
所以我有 2 std::map s >一个是“旧的”,一个是“新的”,我想知道哪些文件被删除了,这样就能够遍历差异并对 shared_ptr 做一些事情。这样的事情可能吗?如何做到? 最佳答案 虽然
是否可以将当前查看的 google.maps.Map 转换为静态图像链接,以便我可以获取图像并将其嵌入到 PDF 中? 我在 map 上添加了一些带有自定义图标的标记,所以我不确定这是否真的可行。 如
你能帮我吗 Java Streams ? 从标题可以看出我需要合并List>>进入Map> . 列表表示为List>>看起来像: [ { "USER_1":{
对于 idAndTags 的第二个条目,内部映射被打乱,但第一个条目则不然 第一次接近! for (Map.Entry> entryOne : idAndTags.entrySet()) {
我将从我的代码开始,因为它应该更容易理解我想要做什么: @function get-color($color, $lightness) { @return map-get(map-get($col
我过去曾在许多网站上使用过 Google map ,但遇到了以前从未遇到过的问题。 map 窗口正在显示,但它只显示左上角的 map 片段,以及之后的任何内容(即使我在周围导航时),右侧也不会加载任何
众所周知,这些 map ,无论是常规街道 map 还是卫星 map ,在中国的特定地区都无法正确排列。那么哪个 map 排列正确,是卫星 map 还是默认街道 map ?一些网站表明卫星 map 是正
在拖尾事件之后,我面临着获取此处 map 中的 map 边界的问题。我需要新的经纬度来在新更改的视口(viewport)中获取一些项目/点。我只是想在拖动结束时获得谷歌地图map.getBounds(
我想做的是通过 ajax API 显示以英国邮政编码为中心的小型 bing 生成 map 。我相信这是可能的;我在 Bing map 文档中找不到如何将英国邮政编码转换为可以插入 map Ajax 控
我有一个 List我想转换成的 e Map>其中外部字符串应为“Name”,内部字符串应为“Domain”。 Name Id Domain e(0) - Emp1, 1, Insuran
我的第 2 部分:https://stackoverflow.com/questions/21780627/c-map-of-maps-typedef-doubts-queries 然后我继续创建 I
是否可以在 1 行中使用 Java8 编写以下所有 null 和空字符串检查? Map> data = new HashMap<>(holdings.rowMap()); Set>> entrySet
我正在审查一个项目的旧代码,并使用 Map 的 Map 的 Map 获得了如下数据结构(3 层 map ): // data structure Map>>> tagTree
这可能是一种不好的做法,但我还没有找到更好的解决方案来解决我的问题。所以我有这张 map // Map>> private Map>> properties; 我想初始化它,这样我就不会得到 Null
我们在 JDK 1.7 中使用 HashMap,我在使用 SonarQube 进行代码审查时遇到了一些问题。 请考虑以下示例: public class SerializationTest imple
我是一名优秀的程序员,十分优秀!