2015-07-21 19 views
3

所以我试图更好地理解monad的想法。我试图从简单开始;那就是用一个返回函数构建一个非常简单的Elixir模块。这:如何在Elixir中编写一个Monadic值?

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> 

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

回答

7

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

monad最常见的形式是将输出从一个函数传递到链中的下一个函数。 Elixir为此提供管道运营商|>。但是:

基于OP,并且不想改变参数数量:

原来的参数传递给指定的函数永远不会被使用。如果你想保持命名的函数的参数数量,而是要通过匿名函数“链接”返回的值,你将实现非匿名的功能,例如:

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) 
+0

你真的试过在iex中运行该代码吗?它不起作用。 iex(2)> f = MonadTest.return **(UndefinedFunctionError)undefined function:MonadTest.return/0 MonadTest.return() –

+0

我确实运行过它,它确实有效。你是否将MonadTest上的参数改为0?注意命名函数不带参数。由于MonadTest.return/1和MonadTest.return/0是elixir中不同的命名函数,所以未定义的函数错误通常表明不同的arity。 –

+0

然后你没有回答这个问题。如果我必须改变组合才能使其工作,那不是一个解决方案。 –

相关问题