【问题标题】:How To Code A Monadic Value In Elixir?如何在 Elixir 中编写一元值?
【发布时间】:2015-08-05 16:23:24
【问题描述】:

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

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

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

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>

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

【问题讨论】:

    标签: monads elixir


    【解决方案1】:

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

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

    基于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)是&amp;&lt;NamedFunction&gt;/&lt;arity&gt;语法,二是参数是如何传递的。

    语法&amp;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)
    

    【讨论】:

    • 您是否真的尝试在 iex 中运行该代码?它不起作用。 iex(2)> f = MonadTest.return ** (UndefinedFunctionError) 未定义函数:MonadTest.return/0 MonadTest.return()
    • 我确实运行了它,它确实有效。您是否将 MonadTest 上的 arity 更改为 0?请注意,命名函数不带参数。由于 MonadTest.return/1 和 MonadTest.return/0 是 elixir 中不同的命名函数,因此未定义的函数错误通常表明存在不同的数量。
    • 那你没有回答这个问题。如果我必须改变 arity 以使其工作,那不是解决办法。
    • 我刚刚编辑了这篇文章,以展示如何在保留原始数量的同时实现游牧式链接。
    • 最近的一个。而且您没有仔细阅读代码。复制并粘贴它,它会工作大声笑。这一切都在 iex 内部得到了验证。更新中的第二个函数不接受参数。您的原始代码在匿名函数内重新定义了命名函数参数。如果您希望两个函数都采用单独的参数,您应该对两者都做一些事情。我基本上已经提供了你所尝试的每一个语法正确的变体。
    猜你喜欢
    • 2018-05-07
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-20
    • 2019-12-02
    • 1970-01-01
    相关资源
    最近更新 更多