小编bob*_*bob的帖子

懒惰和纯洁之间有什么联系?

懒惰是保持 Haskell 纯净的原因。如果是严格的,纯洁很快就会消失。

我看不到语言的评估策略与其纯度之间的联系。考虑到推文作者的声誉,我肯定忽略了一些东西。也许有人可以阐明一些观点。

haskell functional-programming language-implementation lazy-evaluation purity

45
推荐指数
3
解决办法
3558
查看次数

从理论的角度来看,Yoneda Lemma仅有用吗?

例如,可以使用Yoneda获得循环融合:

newtype Yoneda f a =
    Yoneda (forall b. (a -> b) -> f b)

liftYo :: (Functor f) => f a -> Yoneda f a
liftYo x = Yoneda $ \f -> fmap f x

lowerYo :: (Functor f) => Yoneda f a -> f a
lowerYo (Yoneda y) = y id

instance Functor (Yoneda f) where
    fmap f (Yoneda y) = Yoneda $ \g -> y (g . f)

loopFusion = lowerYo . fmap f . fmap g …
Run Code Online (Sandbox Code Playgroud)

haskell functor function-composition

14
推荐指数
2
解决办法
257
查看次数

原始递归和 catamorphisms 之间有什么联系?

对自然数使用以下 catamorphism 我可以实现各种算术算法而不必处理递归:

cataNat :: b -> (b -> b) -> Natural -> b
cataNat zero succ = go
  where
    go n = if (n <= 0) then zero else succ (go (n - 1))

fib :: Natural -> Natural
fib = fst . cataNat (0, 1) (\(a, b) -> (b, a + b))
Run Code Online (Sandbox Code Playgroud)

cataNat对我来说看起来类似于原始递归。无论提供zero和 的哪种组合,至少它的每个应用程序似乎都可以终止succ。在每次迭代中,整个问题都被最小/最简单的问题实例分解。因此,即使它在技术上不是原始递归,它似乎也具有同样的表现力。如果这是真的,则意味着 catamorphism 不足以表达一般递归。为此,我们可能需要一个hylomorphism。我的推理是否正确,也就是说,等价性是否适用于任何类型的 catamorphism,而不仅仅是自然数?

recursion haskell functional-programming fold catamorphism

13
推荐指数
1
解决办法
218
查看次数

比代数数据类型更喜欢 CPS 的要求是什么?

我对代数数据类型的经验很少,因为我使用一种没有本地支持的语言。通常可以使用延续传递风格来获得远程相似的体验,但处理 CPS 编码类型不太舒服。

考虑到这一点,为什么像 Parsec 这样的库会使用 CPS?

newtype ParsecT s u m a
    = ParsecT {unParser :: forall b .
                 State s u
              -> (a -> State s u -> ParseError -> m b) -- consumed ok
              -> (ParseError -> m b)                   -- consumed err
              -> (a -> State s u -> ParseError -> m b) -- empty ok
              -> (ParseError -> m b)                   -- empty err
              -> m b
             }
Run Code Online (Sandbox Code Playgroud)

一个线索是try解析器,它通过在两种情况下传递空错误延续来排除消耗的错误情况:

try :: …
Run Code Online (Sandbox Code Playgroud)

haskell functional-programming algebraic-data-types continuation-passing

13
推荐指数
2
解决办法
197
查看次数

是否应该避免通过符号扩展内置Javascript原型?

这是主要的意见是内置的Javascript原型不应该被延长(或以任何方式改变):

Array.prototype.empty = function () { return this.length === 0; } // don't try that
Run Code Online (Sandbox Code Playgroud)

此规则是否也适用于ES2015符号?

const empty = Symbol("empty");
Array.prototype[empty] = function empty() { return this.length === 0; }
Run Code Online (Sandbox Code Playgroud)

由于symbol是string(原始的,不可变的)和object(标识)的混合,因此根据定义可以没有对象属性命名冲突.

正常对象反射不受符号影响:

Object.getOwnPropertyNames(Array.prototype).indexOf("empty"); // -1
Run Code Online (Sandbox Code Playgroud)

但是ES2015的反思Reflect.ownKeys(Array.prototype)是.

所以这个问题主要是关于我们将来如何使用Reflect.ownKeys和Object.getOwnPropertySymbols未来的问题.

javascript symbols prototype ecmascript-6

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

阵列中的Lodash检查值不区分大小写

我正在使用lodash _.some函数检查数组中的值.但它的情况敏感.在lodash中是否有任何不区分大小写的搜索功能.下面是我的示例数组结构

    [
      {
        "Name": "Division 1",
        "ParentName": null
      },
      {
        "Name": "Division 2",
        "ParentName": null
      }
    ]
Run Code Online (Sandbox Code Playgroud)

使用lodash我正在检查这样

    _.some(divisionList, ['Name', divisionname]);
Run Code Online (Sandbox Code Playgroud)

javascript arrays lodash

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

如何分享延续的中间结果?

请注意,即使此问题中的示例是用Javascript编码的,其基本概念在Haskell中也是常见的,而我虽然更喜欢用Javascript表达自己,但我也很欣赏Haskell中的答案。

在Javascript中,我根据单子原理使用CPS处理异步计算。但是,为了简单起见,我将对这个问题使用正常的延续单子。

一旦我的连续作文增长,我就会发现自己处于需要获得这些作文中间结果的情况。由于必须使用Javascript,因此很容易将此类结果存储在变量中,并在以后访问它们。但是由于我们在谈论连续性,因此访问中间结果意味着调用函数并多次访问它们意味着大量的重新评估。

这似乎非常适合记忆。但是,如果那个函数不返回任何东西而只调用其延续(以及顺便说一句),我该如何记住一个函数的返回值(正如我之前提到的那样,我使用异步函数也不会在Javascript事件循环的当前周期中返回任何东西) )。

似乎我必须提取正确的延续。也许可以通过shift/ 分隔定界符来实现reset,但是我不知道如何应用这些组合器。这个问题可能并没有那么难解决,我只是对持续传递风格的魔幻之地感到困惑……所以请纵容我。

这是ContJava语言中没有备忘的简化示例:

const taggedLog = tag => s =>
  (console.log(tag, s), s);

const id = x => x;

const Cont = k => ({
  runCont: k,
  [Symbol.toStringTag]: "Cont"
});

const contAp = tf => tx =>
  Cont(k => tf.runCont(f => tx.runCont(x => k(f(x)))));

const contLiftA2 = f => tx => ty =>
  contAp(contMap(f) (tx)) (ty);

const contOf = x => Cont(k => k(x));

const contMap = f => …
Run Code Online (Sandbox Code Playgroud)

javascript continuations haskell functional-programming memoization

8
推荐指数
1
解决办法
184
查看次数

如何为我的Task实现实现Promise.all的等效项?

这是我的Task实现方式(即一种Promise但符合monad法律且可取消的方式)。它工作坚如磐石:

const Task = k =>
  ({runTask: (res, rej) => k(res, rej)});

const tAp = tf => tk =>
  Task((res, rej) => tf.runTask(f => tk.runTask(x => res(f(x)), rej), rej));

const tOf = x => Task((res, rej) => res(x));

const tMap = f => tk =>
  Task((res, rej) => tk.runTask(x => res(f(x)), rej));

const tChain = fm => mx =>
  Task((res, rej) => mx.runTask(x => fm(x).runTask(res, rej), rej));

const log = x => console.log(x);
const elog = …
Run Code Online (Sandbox Code Playgroud)

javascript continuations functional-programming continuation-passing

6
推荐指数
1
解决办法
137
查看次数

什么构成了编程上下文中的 codata?

这是一个核心递归算法,因为在每次迭代中,它调用自己的数据大于之前的数据:

iterate f x =  x : iterate f (f x)
Run Code Online (Sandbox Code Playgroud)

它类似于尾递归累加器风格,但它的累加器是隐式的,而不是作为参数传递。如果不是因为懒惰,那将是无限的。那么 codata 只是 WHNF 中值构造函数的结果,有点像(a, thunk)?或者 codata 是范畴论中的一个数学术语,它在编程领域没有有用的表示?

后续问题:值递归只是核心递归的同义词吗?

recursion haskell functional-programming codata corecursion

6
推荐指数
1
解决办法
450
查看次数

如何推断 Scott 编码的 List 构造函数的类型?

Scott 编码列表可以定义如下:

newtype List a =
    List {
      uncons :: forall r. r -> (a -> List a -> r) -> r
    }
Run Code Online (Sandbox Code Playgroud)

与 ADT 版本相反的List是类型和数据构造函数。Scott 编码通过模式匹配来确定 ADT,这实质上意味着删除一层构造函数。这是uncons没有隐式参数的完整操作:

uncons :: r -> (a -> List a -> r) -> List a -> r
--    Nil ^    ^^^^^^^^^^^^^^^^^^ Cons
uncons nil cons (List f) = f nil cons
Run Code Online (Sandbox Code Playgroud)

这是完全有道理的。uncons接受一个常数、一个延续和 aList并产生任何值。

然而,数据构造函数的类型对我来说没有多大意义:

List :: (forall r. r -> (a -> List a -> r) …
Run Code Online (Sandbox Code Playgroud)

haskell functional-programming algebraic-data-types higher-rank-types scott-encoding

6
推荐指数
2
解决办法
130
查看次数