问题标签 [purescript]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
1144 浏览

haskell - 如何在纯脚本中构建应用程序

我决定尝试函数式编程和 Purescript。在阅读"Learn you a Haskell for great good""PureScript by Example"玩了一点代码之后,我认为我可以说我理解了基础知识,但有一件事让我很困扰 - 代码看起来非常耦合。我经常更改库是很常见的,在 OOP 中我可以使用洋葱架构将我自己的代码与库特定的代码分离,但我不知道如何在 Purescript 中执行此操作。

我试图找出人们在 Haskell 中是如何做到这一点的,但我能找到的只是诸如“没有人在 Haskell 中制作过复杂的应用程序,所以没有人知道如何去做”或“你有输入,你有输出”之类的答案, 两者之间的一切都只是纯函数”。但此时我有一个玩具应用程序,它使用了虚拟 dom、信号、网络存储、路由器库,它们每个都有自己的效果和数据结构,所以听起来不像一个输入和一个输出。

所以我的问题是我应该如何构建我的代码或者我应该使用什么技术,这样我就可以在不重写我的应用程序的一半的情况下更改我的库?

更新:

使用多层并在主模块中保留效果的建议也很常见,我理解为什么我应该这样做。
这是一个简单的例子,希望能说明我正在谈论的问题:

在这里,我们有一个简单的计数器应用程序,其中包含路由、Web 存储、dom 操作和控制台日志记录。如您所见,没有单一的输入和单一的输出。我们可以从路由器或事件监听器获取输入,并使用控制台或 dom 作为输出,所以它变得有点复杂。

在主模块中包含所有这些有效的代码对我来说是错误的,原因有两个:

  1. 如果我继续添加路由和控制器,这个模块将很快变成一千行混乱。
  2. 将路由、dom 操作和数据存储在同一个模块中违反了单一职责原则(我认为这在 FP 中也很重要)

我们可以将此模块拆分为多个模块,例如每个控制器一个模块并创建某种有效层。但是当我有十个控制器模块并且我想更改我的 dom 特定库时,我应该全部编辑它们。

这两种方法都远非理想,所以问题是我应该选择哪一种?或者也许还有其他方法可以走?

0 投票
1 回答
330 浏览

monads - 如何使用 Eff Monad 处理副作用

我有点被这个错误信息难住了

这是这段代码的结果

为什么需要统一EffEither?这似乎只在实例化 IsForeign 类型类时出现。 sideeffect运行愉快main- 当然 main 有一个签名,说明它使用 Eff Monad

0 投票
1 回答
1184 浏览

purescript - 如何编写一个从集合中减去效果的纯脚本效果处理程序

PureScript by Example,在The Eff Monad -> Handlers and Actions一节中指出“[效果] 处理程序通常会从集合中减去效果”。但是,这些示例相当不透明,我无法弄清楚如何编写自己的处理程序来实现这一点。

具体来说,我正在使用 purescript-aff 和purescript-affjax。我想将 runAff(来自 purescript-aff)与 get(来自 purescript-affjax)结合使用。

问题是get使用 Affjax monad,而runAff期望使用 Aff monad。

Affjax 定义为:

Aff 定义为:

因此,我想编写一个具有以下类型的函数:

在我看来,这似乎需要一个处理程序来减去ajax效果集的一部分。如何编写这样的处理程序?

尝试进行模式匹配,如下所示,当然会导致错误unexpected |

谢谢大家。

更新

@christoph-hegemann下面的回答启发,我能够找到我的代码的大部分问题。

我认为标题中问题的答案是不会从集合中减去效果,而且这种描述有点令人困惑。处理后效果仍然存在。

我缺少的直觉是我必须将预期效果添加到调用函数类型。缺少类型声明在main某种程度上隐藏了这一点。当我将 Christoph 的示例转换为以下编译示例时,我解决了这个问题:

0 投票
1 回答
251 浏览

monad-transformers - 用于卤素元件的 Monad 变压器

我试图弄清楚我可以通过哪种方式在卤素组件包含的单子上使用变压器。

我想通过带有 Config 记录的 ReaderT 扩展介绍示例,在这种情况下,可以使用它来使字符串可配置,但是在将它们放在一起时我迷失了。

假设我们这样定义我们的 Config:

然后我们的ui函数将从

forall m eff. (Monad m) => Component m Input Input

forall m (Monad m) => Component (ReaderT Config m) Input Input.

为了评估我们的 main 函数,我们将使用hoistComponent它来将其转换回以前的形式:

到目前为止,我不确定这是否有意义,但假装它确实如此,下一步就是我正在努力的地方。在理想的世界中,我的 ui 函数将允许我执行以下操作:

但我最终遇到了一长串统一错误,不知道从哪里开始。显然,内部使用ask不能像这样工作,因为我需要将它提升到 HTML 上下文中,但我什至不确定这是否可能。

如果有人可以指导我了解这里的类型并告诉我这种通用方法是否明智,那就太好了。GitHub 上有一个完整的(非编译)示例。I18n 应仅作为此处阅读器的简单示例使用。

0 投票
1 回答
118 浏览

typeclass - 类型类、实例和包装器

有人可以向我解释为什么这个(版本 1)可以编译,而下面的版本(版本 2)没有。

这不编译

并给我这个错误

那么如何制作类似于我的版本 2 的版本,以便我可以将我的结果放入包装器中?

0 投票
2 回答
248 浏览

functional-programming - 什么时候功能应该有效?

当我使用 FFI 包装一些 API(例如 DOM API)时,是否有任何经验法则可以帮助我决定函数是否应该有效?

这是一个例子:

感觉querySelector很有效,但我不太确定getTagName

更新:

我明白什么是纯函数,它不应该改变程序的状态,也许 DOM 是一个不好的例子。

我问这个问题是因为在大多数包装现有 js 库的库中,几乎每个函数都是有效的,即使感觉不对。所以也许我的实际问题是 - 这种效果是否代表了这个包装好的 js lib 中的需要,或者它是否存在以防万一它内部是有状态的?

0 投票
1 回答
166 浏览

functional-programming - 效果和幻象类型

假设我们有三个对象:

FirstObj并使用自己的属性和方法SecondObj继承someProp和扩展它。使用可以是任何东西的 state 属性(和 get/set 方法)进行扩展。toggleSomePropMainObjSecondObjMainObj

假设我们有两个对象FirstObjSrcSecondObjSrc它们都有getObj方法。第一个返回FirstObj,第二个返回SecondObj

这就是我看到它在 Purescript 中实现的方式:

所以,我对这段代码有一些疑问:

  1. 这个实现正确吗?
  2. ObjEff效果需要幻影类型吗s
  3. 如果有(或没有),那么我想了解原因(我已经阅读了https://wiki.haskell.org/Phantom_type和其他一些的解释,我认为我了解基础知识,但效果让我有点困惑)。

更新

假设上面的代码是某种虚构的浏览器(或 NodeJS)API,因此无法以某种方式对其进行更改。

0 投票
1 回答
925 浏览

ffi - 使用 purescript 的 FFI 调用带有回调的 js 函数

我正在尝试navigator.geolocation.getCurrentPosition从 purescript 调用 javascript 函数,但遇到了两个问题。

在 javascript 中,它会使用类似的东西来调用

其中位置是一个对象。

首先,我不知道返回类型应该是什么,因为它不返回任何内容,而是调用回调。

其次,我不知道回调使用什么类型,因为函数不能是纯的,因为它的结果不会被返回。

到目前为止我有

所以这里我的外部函数的类型签名是forall eff a. Eff (geolookup :: GeoLookup | eff) {},但是我知道在 Eff 之前也应该有一个回调参数。我只是不确定如何编写类型签名或实现它。

0 投票
1 回答
594 浏览

gadt - 数据构造函数中的 Rank-2 类型

我一直在尝试使用 rank-2 类型在 PureScript 中对 GADT 进行编码,如此处所述Haskell

我的代码如下所示:

编译器抱怨Wrong number of arguments to constructor Main.Cons,指的是 Functor 实例中的 LHS 模式匹配。

这里出了什么问题?

问候,

迈克尔

0 投票
1 回答
545 浏览

haskell - 处理(深度嵌套)仿函数的正确方法是什么?

我有以下简单的代码

在哪里

返回类似的东西

返回类似的东西

现在我有一个深深嵌套的Maybe。这使得使用起来有点困难(即使使用函子)。我给自己写了一对辅助函数——但我对此有点不满意。不知何故感觉不对劲。

然后像这样使用它

在 Purescript/Haskell 中是否有更好/惯用的方法来做这些事情?