我最近又在探索 TypeScript。它的关键限制之一似乎是无法键入函数组合。让我首先向您展示 JavaScript 代码。我正在尝试输入:
const getUserById = id => new Promise((resolve, reject) => id === 1
? resolve({ id, displayName: 'Jan' })
: reject('User not found.')
);
const getName = ({ displayName }) => displayName;
const countLetters = str => str.length;
const asyncIsEven = n => Promise.resolve(n % 2 === 0);
const asyncPipe = (...fns) => x => fns.reduce(async (y, f) => f(await y), x);
const userHasEvenName = asyncPipe(
getUserById,
getName,
countLetters,
asyncIsEven
);
userHasEvenName(1).then(console.log);
// ? false
userHasEvenName(2).catch(console.log);
// …Run Code Online (Sandbox Code Playgroud) asynchronous functional-programming function-composition promise typescript
我创建了一个将函数链接在一起的函数。我创建了一堆通用类型来正确关联结果函数可以具有的参数。您可以在此处阅读有关此范例的更多信息、我正在寻找的内容以及我创建它的原因。
一切正常……到了一定程度。由于我生成类型的方式,当链变得太长时,TypeScript 会失败。我正在寻找一种方法来缓解这个问题。
我收到此错误:
Type instantiation is excessively deep and possibly infinite.
毫无疑问,这对于 TypeScript 来说太多了,而且随着每个函数的添加,类型映射呈指数级增长。
我意识到这段代码相当复杂,所以我不是在寻找完整的技术解决方案,只是寻找一种更符合 TypeScript 的/算法更简单的方法来做同样的事情。
namespace Poly {
export type Omit<T, K extends string | number | symbol> = { [P in Exclude<keyof T, K>]: T[P]; }
}
namespace Use {
type ThenArg<T> = T extends Promise<infer U> ? U : T
type RelatedThen<A, B> = A extends Promise<infer U> ? Promise<B> : B
export type Func = (...args: any[]) => any
export type Return<A extends …Run Code Online (Sandbox Code Playgroud) composition infinite-loop control-flow function-composition typescript
我正在尝试创建一个由函数 f(x) 组成 N 次的函数,类似于:
function CompositionN(f,N)
for i in 1:N
f(x) = f(f(x))
end
return f(x)
Run Code Online (Sandbox Code Playgroud)
我需要函数 CompositionN 返回另一个函数,而不是值。
从一个很棒的网站阅读高阶函数页面后,我仍然无法理解与函数组合配对的否定函数.
更具体地说,拿这段代码:
ghci> map (negate . sum . tail) [[1..5],[3..6],[1..7]]
Run Code Online (Sandbox Code Playgroud)
产量:
[-14,-15,-27]
Run Code Online (Sandbox Code Playgroud)
我重新阅读了这个页面,但说实话,我仍然不知道这行代码是如何产生这个答案的,如果有人能指引我完成这个过程,我会非常感激!
我非常精通在F#中使用>>和<<运算符.然而,在查看F#源以建立更深入的理解之后,我对此感到困惑:
let inline (>>) f g x = g(f x)
let inline (<<) f g x = f(g x)
Run Code Online (Sandbox Code Playgroud)
我如何从概念上解释这些表达?另外,你会如何形容这些表达?他们定义了一种类型吗?
如果我有一个功能列表,每种类型a -> a的某种类型,最简洁,优雅和惯用的方式组合它们; 最好不要添加额外的依赖项?
一些变体包括
foo (x:xs) = x . (foo xs)
foo [] = id
Run Code Online (Sandbox Code Playgroud)
和
foo = foldr (.) id
Run Code Online (Sandbox Code Playgroud)
和
foo = appEndo . mconcat . map Endo
Run Code Online (Sandbox Code Playgroud)
但由于某种原因,我期待找到更好的东西.
我只看过如下组合函数(或使用lambdas的人)的例子.
Function<A,B> inner = ....;
Function<B,C> outter = ....;
Function<A,C> result = outter.compose(inner);
Run Code Online (Sandbox Code Playgroud)
我想使用"compose"功能编写以下函数,而不是直接调用它们.
public class J{
public static B inner(final A a){...}
public static C outter(final B b){...}
}
public class K{
public static Function<A,C> result = (J::outter).compose(J::inner);
}
Run Code Online (Sandbox Code Playgroud)
这不编译.我似乎无法使用java.util.function.Function的"compose"成员.我如何为传统声明的函数执行此操作?我想避免以下情况:
public class K{
public static Function<A,C> result = (a)-> J.outter(J.inner(a));
}
Run Code Online (Sandbox Code Playgroud)
可以吗?提前致谢
以下是我尝试将四个函数组合成一个端点字符串:
const endpoint = str => `${str}` || 'default'
const protocol = str => `https://${str}`
const params = str => `${str}?sort=desc&part=true&`
const query = str => `${str}query={ some:'value', another:'value'}`
let finalEndpoint = R.compose(query, params, protocol, endpoint)
var result = finalEndpoint('api.content.io')
Run Code Online (Sandbox Code Playgroud)
这个组合工作并返回我想要的结果:
https://api.content.io?sort=desc&part=true&query={ some:'value', another:'value'}
Run Code Online (Sandbox Code Playgroud)
但请注意我是如何对其函数体内部和内部的值进行硬编码的.我看到只有一个值超过了这个链中的值.paramsqueryR.compose
我如何以及在何处将参数传递给参数和查询参数?
更新:
我做的是curried那些函数:
var R = require('ramda');
const endpoint = str => `${str}` || 'default'
const protocol = str => `https://${str}`
const setParams = R.curry ( (str, params) …Run Code Online (Sandbox Code Playgroud) 我想了解(>>=).(>>=),GHCi告诉我的是:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
(>>=).(>>=) :: Monad m => m a -> (m b -> (a -> m b) -> b1) -> (a -> m b) -> b1
Run Code Online (Sandbox Code Playgroud)
你能提供一步一步解释结果的来源吗?
这种作品曾被使用过吗?
更新:
我能够解决fmap.fmap但不能退出(>>=).(>>=),我能够达到(.)(>>=) :: Monad m => (a1 -> m a) -> a1 -> (a -> m b) -> m b但后事情开始变得有些混乱.任何帮助将不胜感激,只是想在这里学习.
我经历了理查德·伯德的"哈斯克尔功能的思考"一书,并且存在在那里他证明了滤波方法的属性我无法理解的部分.他证明的是:
filter p . map f = map f . filter (p . f)
Run Code Online (Sandbox Code Playgroud)
在本书的前面,他将过滤器定义为:
filter p = concat . map (test p)
test p x = if p x then [x] else []
Run Code Online (Sandbox Code Playgroud)
这就是他证明第一个等式的方法:
filter p . map f
= {second definition of filter} -- He's referring to the definition I gave above
concat . map (test p) . map f
= {functor property of map}
concat . map (test p . f)
= {since test p . f …Run Code Online (Sandbox Code Playgroud) haskell ×4
composition ×2
function ×2
typescript ×2
asynchronous ×1
control-flow ×1
equality ×1
f# ×1
java ×1
julia ×1
lambda ×1
map-function ×1
monads ×1
mutable ×1
negate ×1
pointfree ×1
promise ×1
proof ×1
ramda.js ×1
repeat ×1