monads - 如何在 Elixir 中编写一元值?

标签 monads elixir

所以我试图更好地理解单子(monad)的概念。我试图从简单开始;那就是构建一个非常简单的 Elixir 模块,只有一个返回函数。这个:

defmodule MonadTest do
   def return(s), do: fn s -> s end
end

然后我以这种方式将函数绑定(bind)到一个变量:

f = &MonadTest.return/1

然后我尝试这样调用函数:

f.(12)

但我没有返回 12,而是得到了函数。像这样:

iex(22)> r = f.(12)
#Function<0.122071921/1 in MonadTest.return/1>
iex(23)> r
#Function<0.122071921/1 in MonadTest.return/1>

我确定我遗漏了一些明显的东西——但我在这里遗漏了什么?

最佳答案

monad 是一种描述操作如何链接在一起的方式

monad 最常见的形式是将输出从一个函数传递到链中的下一个函数。 Elixir 提供管道运算符(operator)|>为了那个原因。然而:

基于OP,不想改变arity:

从未使用过传递给命名函数的原始参数。如果您想保持命名函数的数量,但希望匿名函数“链接”返回值,则可以这样实现非匿名函数:

  defmodule MonadTest do
    def return(s), do: fn -> s end
  end
  f = MonadTest.return(1)
  f.()

或者,您可以像在帖子中那样匿名使用该功能:

  defmodule MonadTest do
    def return(s), do: fn -> s end
  end
  f = &MonadTest.return/1
  f.(1).()

我认为我们可以澄清两件事。 (1) 是&<NamedFunction>/<arity>语法,二是参数的传递方式。

语法&MonadTest.return/1将生成一个与命名函数 MonadTest.return 相同定义的匿名函数.

这通常在将命名函数作为参数传递时使用,例如如果您需要在可枚举方法中使用 MonadTest.return/1,例如 Enum.map(1..5, &MonadTest.return/1)。

在我的示例中,我不会将参数传递给命名函数,因为您将它传递给新定义的 MonadTest.return/0 内的匿名函数。

出于您的目的,您可能不需要生成匿名函数,而是可以直接引用命名函数:

  defmodule MonadTest do
    def return, do: fn s -> s end
  end
  f = MonadTest.return
  f.(12)

如果您确实需要 MonadTest 是匿名的,则需要调用它,然后将参数传递给嵌套在其中的匿名函数。

  defmodule MonadTest do
    def return, do: fn s -> s end
  end
  f = &MonadTest.return/0
  f.().(12)

关于monads - 如何在 Elixir 中编写一元值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31544681/

相关文章:

haskell - 自己实现的forM,找不到错误

websocket - 我如何知道 Phoenix channel 的连接数量?

当有大量节点或二进制数据时 Erlang 消息

elixir - (RuntimeError) 预期连接有响应

haskell - 绑定(bind)多个参数

list - 为什么我们有map、fmap和liftM?

unit-testing - 有没有办法使用 Elixir 中的 Doctest 测试 IO 输出?

elixir - Phoenix 应用中的自定义混音任务

Haskell:如何将一个句柄的内容实时传递到另一个句柄

haskell - 在运行时选择一个 monad