2015-07-21 51 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

然後你沒有回答這個問題。如果我必須改變組合才能使其工作,那不是一個解決方案。 –

相關問題