标签: lifting

什么是Scala中的"提升"?

有时,当我阅读Scala生态系统中的文章时,我会读到"提升"/"解除"一词.不幸的是,没有解释这究竟意味着什么.我做了一些研究,似乎提升与功能价值或类似的东西有关,但我无法找到一个文本,以初学者友好的方式解释实际提升的内容.

通过Lift框架存在额外的混乱,其名称已经提升,但它无助于回答这个问题.

什么是Scala中的"提升"?

functional-programming scala function lifting

245
推荐指数
4
解决办法
3万
查看次数

C#Lambda性能问题/可能性/指南

我正在使用各种lambda表达式语法测试性能差异.如果我有一个简单的方法:

public IEnumerable<Item> GetItems(int point)
{
    return this.items.Where(i => i.IsApplicableFor(point));
}
Run Code Online (Sandbox Code Playgroud)

然后这里有一些与point参数相关的变量提升,因为它是lambda视角的自由变量.如果我将这种方法称为百万次,那么保持原样或以任何方式改变它以改善其性能会更好吗?

我有哪些选择,哪些选项实际可行?据我所知,我必须摆脱自由变量,因此编译器不必创建闭包类并在每次调用此方法时实例化它.与非闭合版本相比,此实例化通常需要大量时间.

问题是我想提出一些通常会起作用的lambda写作指南,因为看起来每次我写一个受到重创的lambda表达式时我都会浪费一些时间.我必须手动测试它以确保它能够工作,因为我不知道要遵循什么规则.

替代方法

&示例控制台应用程序代码

我还写了一个不同版本的同一个方法,不需要任何变量提升(至少我认为它没有,但你了解这个让我知道是否是这种情况):

public IEnumerable<Item> GetItems(int point)
{
    Func<int, Func<Item, bool>> buildPredicate = p => i => i.IsApplicableFor(p);
    return this.items.Where(buildPredicate(point));
}
Run Code Online (Sandbox Code Playgroud)

在这里查看Gist.只需创建一个控制台应用程序并将整个代码复制到块Program.cs内的文件中namespace.您将看到第二个示例即使不使用自由变量也要慢得多.

一个矛盾的例子

我想构建一些lambda最佳使用指南的原因是我之前遇到过这个问题,令我惊讶的是,当使用谓词构建器 lambda表达式时,结果更快.

现在解释一下.我完全迷失在这里,因为当我知道我的代码中有一些繁重的使用方法时,我可能根本不会使用lambdas.但我想避免这种情况,并深究这一切.

编辑

你的建议似乎不起作用

我已经尝试实现一个自定义查找类,其内部工作方式与编译器使用自由变量lambda类似.但是,我没有使用闭包类,而是实现了模拟类似场景的实例成员.这是代码:

private int Point { get; set; }
private bool IsItemValid(Item item)
{
    return item.IsApplicableFor(this.Point);
}

public IEnumerable<TItem> GetItems(int point)
{ …
Run Code Online (Sandbox Code Playgroud)

c# lambda performance-testing lifting

28
推荐指数
1
解决办法
2635
查看次数

是否可以在Scala中实现liftM2?

在Haskell中,liftM2可以定义为:

liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 f m1 m2 = do
  x1 <- m1
  x2 <- m2
  return $ f x1 x2
Run Code Online (Sandbox Code Playgroud)

我想把它翻译成Scala.我的第一次尝试如下:

def liftM2[T1, T2, R, M[_]](f: (T1, T2) => R)(ma: M[T1], mb: M[T2]) : M[R] = for {
  a <- ma
  b <- mb
} yield f(a, b)
Run Code Online (Sandbox Code Playgroud)

我认为这是最明显的可行方式:"flat flatMap不是类型参数M [T1]的成员".是的,我没有说明M[_]是某种单子.所以接下来我尝试的是定义一些结构类型,如:

type Monad[A] = {
  def flatMap[B](f: (A) => …
Run Code Online (Sandbox Code Playgroud)

monads haskell scala typeclass lifting

28
推荐指数
1
解决办法
1311
查看次数

如何分解成员访问表达式链?

短版(TL; DR):

假设我有一个表达式,它只是一个成员访问运算符链:

Expression<Func<Tx, Tbaz>> e = x => x.foo.bar.baz;
Run Code Online (Sandbox Code Playgroud)

您可以将此表达式视为子表达式的组合,每个子表达式包含一个成员访问操作:

Expression<Func<Tx, Tfoo>>   e1 = (Tx x) => x.foo;
Expression<Func<Tfoo, Tbar>> e2 = (Tfoo foo) => foo.bar;
Expression<Func<Tbar, Tbaz>> e3 = (Tbar bar) => bar.baz;
Run Code Online (Sandbox Code Playgroud)

我想要做的是分解e成这些组件子表达式,以便我可以单独使用它们.

更短的版本:

如果我有表达x => x.foo.bar,我已经知道如何中断x => x.foo.如何拉出其他子表达式foo => foo.bar

为什么我这样做:

我试图在C#中模拟"提升"成员访问操作符,就像CoffeeScript的存在访问操作符一样?..Eric Lippert表示,类似的运营商被考虑用于C#,但没有预算来实施它.

如果这样的运算符存在于C#中,您可以执行以下操作:

value = target?.foo?.bar?.baz;
Run Code Online (Sandbox Code Playgroud)

如果target.foo.bar.baz链的任何部分结果为null,那么整个事情将评估为null,从而避免NullReferenceException.

我想要一个Lift可以模拟这种事情的扩展方法:

value = target.Lift(x => x.foo.bar.baz); //returns target.foo.bar.baz or null
Run Code Online (Sandbox Code Playgroud)

我试过的: …

c# lambda expression-trees nullreferenceexception lifting

22
推荐指数
1
解决办法
3650
查看次数

无法在Ramda.js中绕着"电梯"环绕我的脑袋

查看Ramda.js的来源,特别是"升力"功能.

电梯

liftN

这是给定的例子:

var madd3 = R.lift(R.curry((a, b, c) => a + b + c));

madd3([1,2,3], [1,2,3], [1]); //=> [3, 4, 5, 4, 5, 6, 5, 6, 7]
Run Code Online (Sandbox Code Playgroud)

因此结果的第一数目是容易的,a,b,和c,是每个阵列的所有的第一元素.第二个对我来说并不容易理解.参数是每个数组的第二个值(2,2,未定义)还是第一个数组的第二个值以及第二个和第三个数组的第一个值?

即使无视这里发生的事情的顺序,我也没有真正看到它的价值.如果我在没有lift它的情况下执行它,我将最终将数组concat作为字符串.这似乎有点像,flatMap但我似乎无法遵循其背后的逻辑.

javascript functional-programming lifting ramda.js

22
推荐指数
3
解决办法
3679
查看次数

在Haskell中提升高阶函数

我正在尝试构造一个类型的函数:

liftSumthing :: ((a -> m b) -> m b) -> (a -> t m b) -> t m b
Run Code Online (Sandbox Code Playgroud)

tmonad变压器在哪里?具体来说,我有兴趣这样做:

liftSumthingIO :: MonadIO m => ((a -> IO b) -> IO b) -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)

我摆弄了一些Haskell巫术库,但无济于事.我如何做到正确,或者在某个我找不到的地方有一个现成的解决方案?

haskell higher-order-functions lifting

18
推荐指数
1
解决办法
956
查看次数

整理Monad - 将monad变换器的应用转换为newtype monad

我试图采取例如ExceptT a (StateT A M),对于一些具体类型A和monad M,并将它们包装到我的新自定义monad中.

首先,我确定了StateT A M在其他环境中经常出现,因此我决定这将是最好的单独包装在一个单子M1,然后包装ExceptT a M1M2.

所需的属性是make M1和的M2实例MonadState和类M(假设它被调用MyMonadClass).也M2应该是一个实例MonadError.

首先我从简单类型的同义词开始:

type MyState    = StateT A M
type MyBranch a = ExceptT a MyState
Run Code Online (Sandbox Code Playgroud)

然后我想我会首先勾画实例声明(没有实现实例),这就是我第一次被卡住的地方.instance MonadState A (MyState)似乎不是正确的语法.我以为我必须创建newtype MyState' a = StateT a M然后type MyState = MyState A(不要在没有必要的地方使用语言扩展).

然而,一旦我开始将同义词转换为newtype声明,我开始失去与StateT A M和 …

haskell state-monad monad-transformers newtype lifting

9
推荐指数
1
解决办法
547
查看次数

变形金刚下的转型

我现在对monad变形金刚有点困难.我正在定义一些利用变压器的不同的非确定性关系.不幸的是,我无法理解如何从一个有效的模型转换到另一个有效的模型.

假设这些关系是"foo"和"bar".假设"foo"将As和Bs与Cs联系起来; 假设"bar"将Bs和Cs与Ds联系起来.我们将用"foo"来定义"bar".为了使事情变得更有趣,这些关系的计算将以不同的方式失败.(由于条形关系取决于foo关系,因此其失败情况是超集.)因此,我给出以下类型定义:

data FooFailure = FooFailure String
data BarFailure = BarSpecificFailure | BarFooFailure FooFailure
type FooM = ListT (EitherT FooFailure (Reader Context))
type BarM = ListT (EitherT BarFailure (Reader Context))
Run Code Online (Sandbox Code Playgroud)

我希望能够用以下函数签名编写关系:

foo :: A -> B -> FooM C
bar :: B -> C -> BarM D
Run Code Online (Sandbox Code Playgroud)

我的问题是,写"酒吧"的定义的时候,我需要能够从"富"的关系接收错误和正确地表示他们在"酒吧"的空间.所以我可以使用表单的功能

convert :: (e -> e') -> ListT (EitherT e (Reader Context) a
                     -> ListT (EitherT e' (Reader Context) a
Run Code Online (Sandbox Code Playgroud)

我甚至可以通过运行ListT,在EitherT上映射,然后重新组装ListT来编写那个小野兽(因为它发生m [a]可以转换为ListT ma).但这似乎......凌乱.

有一个很好的理由我不能只运行变压器,在它下面做一些东西,并且通常"把它放回去"; 我跑的变压器可能有效果,我不能神奇地撤消它们.但是有一些方法我可以将一个函数提升到变压器堆栈中,为我做一些工作,所以我不必编写convert上面显示的函数吗?

monads haskell lifting

7
推荐指数
1
解决办法
159
查看次数

提升自动提取到ExceptT

假设我有这个(可以说是误导的)代码片段:

import System.Environment (getArgs)
import Control.Monad.Except

parseArgs :: ExceptT String IO User
parseArgs =
  do
    args <- lift getArgs
    case safeHead args of
      Just admin -> parseUser admin
      Nothing    -> throwError "No admin specified"

parseUser :: String -> Either String User
-- implementation elided

safeHead :: [a] -> Maybe a
-- implementation elided

main =
  do
    r <- runExceptT parseArgs
    case r of
      Left  err -> putStrLn $ "ERROR: " ++ err
      Right res -> print res
Run Code Online (Sandbox Code Playgroud)

ghc 给我以下错误:

Couldn't …
Run Code Online (Sandbox Code Playgroud)

monads haskell monad-transformers either lifting

7
推荐指数
1
解决办法
988
查看次数

为什么我可以将功能传递给提升的R.divide?

鉴于以下内容:

var average = R.lift(R.divide)(R.sum, R.length)
Run Code Online (Sandbox Code Playgroud)

为什么这会作为一个无点的实现average?我不明白为什么我可以通过R.sum,R.length当它们是函数时,因此,我无法映射提升R.divide函数,R.sumR.length不像下面的例子:

var sum3 = R.curry(function(a, b, c) {return a + b + c;});
R.lift(sum3)(xs)(ys)(zs)
Run Code Online (Sandbox Code Playgroud)

另外,在上述情况下,在值xs,yszs相加在一个非确定性上下文中,在这种情况下,提升函数被应用到的值在给定的计算上下文.

进一步阐述,据我所知,施加解除功能就像使用R.ap连续到每个参数.两行都评估相同的输出:

R.ap(R.ap(R.ap([tern], [1, 2, 3]), [2, 4, 6]), [3, 6, 8])
R.lift(tern)([1, 2, 3], [2, 4, 6], [3, 6, 8])
Run Code Online (Sandbox Code Playgroud)

检查文档说:

"提升"arity> 1的函数,以便它可以"映射"满足FantasyLand Apply规范的列表,函数或其他对象.

这对我来说似乎不是一个非常有用的描述.我正试图建立一个关于使用的直觉lift.我希望有人可以提供.

javascript functional-programming lifting ramda.js

7
推荐指数
1
解决办法
227
查看次数