2016-09-10 48 views
3

我目前正在嘗試學習OCaml。我正在尋找的這個Python代碼相當於:在OCaml中使用列表作爲函數的參數

f(*l[:n]) 

我想我會嘗試寫模仿此行爲的功能,但它不能正常工作。下面是代碼:

let rec arg_supply f xs n = 
    if n = 0 then 
     f 
    else 
     match xs with 
     | x :: remainder -> arg_supply (f x) remainder (n - 1);; 

,這裏是錯誤消息我得到:

Error: This expression has type 'a but an expression was expected of type 
'b -> 'a 
The type variable 'a occurs inside 'b -> 'a 

任何幫助表示讚賞,無論是一個辦法讓我的功能工作,或另一種方式來提供第一列表中的n個元素作爲參數。

編輯:n是調用該函數所需的參數數量,並且因爲它而不變。

編輯:這一個也不工作。取決於n

type ('a, 'r) as_value = ASFunction of ('a -> ('a, 'r) as_value) | ASReturnValue of 'r;; 

let rec _arg_supply f_or_rval xs n = 
    if n = 0 then 
     f_or_rval 
    else 
     match f_or_rval with 
     | ASFunction func -> (
      match xs with 
       | x :: r -> _arg_supply (func x) r (n - 1) 
       | _ -> failwith "too few arguments for f" 
     ) 
     | ASReturnValue out -> out;; 
+0

你不能那樣做。 'arg_supply'的類型必須取決於'n'的運行時值。 – melpomene

+1

這是一個典型的[XY問題](http://xyproblem.info/)。你能解釋一下你真正想做的嗎? – Drup

+0

@Drup我想調用一個函數,其中我的參數在列表中,而不必寫'name_of_the_function(List.nth li 0)(List.nth li 1)(List.nth li 2)...'。 而且我知道我嘗試過的解決方案即使工作也無濟於事,因爲返回類型必須是ASFunction,而不是。但是我可以「擴展」我的功能以適應這種類型。 – CodenameLambda

回答

3

你的Python功能f正在傳遞的參數不同的號碼,。這在OCaml中不能表達。函數需要一個靜態固定數量的參數(即,您可以通過閱讀源代碼來了解參數的數量)。

將不同數量的參數傳遞給OCaml函數的方法是傳遞一個對應於Python代碼f(l[:n])的列表。

(這是更準確的說,一個OCaml的函數有一個說法,但這是另一次的討論。)

更新

如果n實際上是一個常數,讓我們說這是3然後你可以這樣做以下:

match l with 
| a :: b :: c :: _ -> f a b c 
| _ -> failwith "too few arguments for f" 

更新2

下面是看看你想要做什麼的另一種方法。你想編寫一個函數,我們稱之爲apply,即是這樣的:

let apply f xs = 
    . . . 

的想法是,apply調用函數f,給它從列表xs參數。

OCaml是一種強類型語言,所以我們應該能夠給出fxs的類型。什麼是f的類型?您希望它是n參數的函數,其中nxs的長度。即,n不是一個常數!但OCaml中沒有這種類型。任何函數類型都有一個固定的靜態數量的參數。由於f沒有OCaml類型,因此不能編寫函數apply。您可以編寫一系列功能apply1apply2等等。請注意,每個功能都有不同的類型。如果你不介意爲每個不同的功能f調用正確的,那就行了。

很有可能你可以重構你的問題來處理OCaml的輸入而不是掙扎。我堅持我對強打字的評論:一旦你習慣了強打字,很難放棄好處,回到少打(或不打打)輸入支持的語言。

+0

對不起,我沒有在我的問題中澄清它。 n是f所需的參數的數量,並且是常量。這就是'[:n]'的原因。 – CodenameLambda

+0

我傾向於懷疑'n'實際上是一個常數。否則,你會寫f(* l [:3])。但是爲任何給定的'n'值編寫代碼並不難。請參閱上面的**更新**。 –

+0

這將意味着我應該創建arg_supply_1,arg_supply_2,... 這不是我真正想要的。如果我不需要每個人都可以。 – CodenameLambda