如何在Elixir中编码Monadic值?

Ono*_*cci 3 monads elixir

所以我试图更好地理解monad的想法.我试着开始简单; 这是一个非常简单的Elixir模块,只有一个返回功能.这个:

defmodule MonadTest do
   def return(s), do: fn s -> s end
end
Run Code Online (Sandbox Code Playgroud)

然后我以这种方式将函数绑定到变量:

f = &MonadTest.return/1
Run Code Online (Sandbox Code Playgroud)

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

f.(12)
Run Code Online (Sandbox Code Playgroud)

但是我没有回到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>
Run Code Online (Sandbox Code Playgroud)

我确定我错过了一些明显的东西 - 但我在这里错过了什么?

The*_*sor 7

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

monad最常见的形式是将输出从一个函数传递到链中的下一个函数.Elixir |>为此提供管道操作员.然而:

基于OP,不想改变arity:

传递给指定函数的原始参数永远不会被使用.如果你想维护命名函数的arity,但想要匿名函数"chained"返回值,你可以实现非匿名函数:

  defmodule MonadTest do
    def return(s), do: fn -> s end
  end
  f = MonadTest.return(1)
  f.()
Run Code Online (Sandbox Code Playgroud)

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

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

我认为这里有两件事我们可以澄清.(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)
Run Code Online (Sandbox Code Playgroud)

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

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

  • 最近的一个.而且你没有仔细阅读代码.复制并粘贴它,它将工作大声笑.这一切都在iex中得到验证.更新中的第二个函数不接受参数.您的原始代码重新定义了匿名函数内的命名函数参数.如果您希望两个函数都采用单独的参数,则应该对两者都执行某些操作.我基本上提供了你正在尝试的每个语法上正确的变体. (2认同)