是否可以在參數列表上執行foldLeft
,其中提供給fold的初始值是完全curried函數,運算符是apply
,列表是要傳遞給函數f
的參數列表?在Scala中使用foldLeft對curried函數應用參數列表
例如,假設f定義爲:
scala> val f = (i: Int, j: Int, k: Int, l: Int) => i+j+k+l
f: (Int, Int, Int, Int) => Int = <function4>
對此我們當然可以直接使用:
scala> f(1, 2, 3, 4)
res1: Int = 10
或者咖喱和應用的參數每次一個:
scala> f.curried
res2: Int => Int => Int => Int => Int = <function1>
scala> f.curried.apply(1).apply(2).apply(3).apply(4)
res3: Int = 10
乍一看,這看起來像一個foldLeft
的工作。
我在使用foldLeft
描述的apply
此序列第一次嘗試看起來像:
scala> List(1, 2, 3, 4).foldLeft(f.curried)({ (g, x) => g.apply(x) })
然而,產生以下錯誤:
<console>:9: error: type mismatch;
found : Int => Int => Int => Int
required: Int => Int => Int => Int => Int
List(1, 2, 3, 4).foldLeft(f.curried)({ (g, x) => g.apply(x) })
我的錯誤消息的讀數是類型推斷將需要一些暗示g
。
我在尋找解決辦法離開我的一切原始表達式未修改除外g
類型:
List(1, 2, 3, 4).foldLeft(f.curried)({ (g: ANSWER, x) => g.apply(x) })
我首先想到的是,一個聯合類型在這裏很有用。我已經看到了邁克爾薩賓用庫裏霍華德推導出的聯盟類型,所以如果第一次預感是真的,那麼我似乎有解決問題所需的基本機制。
但是:即使union類型是答案,如果我可以引用「從完全curried類型的函數到curried函數類型的所有類型的聯合,並提供除最後一個參數以外的所有類型」。換句話說,一個辦法把類型:
T1 => ... => Tn
到聯合類型:
(T1 => ... => Tn) |∨| ... |∨| (Tn-1 => Tn)
將是作爲用於上述g
類型是有用的。
否則在List
foldLeft
一個限制的討論情況下T1
通過Tn-1
都是相同的。類似
(T1 =>)+ Tn
將描述我想爲g
提供的類型。
我問不需要任意長鏈的具體情況,所以我們可以使用
(T1 =>){1,4} Tn
在想對於不是類型鏈做到這一點展望未來提供的迭代器範圍平等的,但是,也許在某些類型的神奇功能是砍下了鏈到集合中的所有後綴是比較有用的:
Suffixes(T1 => ... => Tn)
實現這個遠遠超出目前我的斯卡拉能力。值得讚賞的是如何去做這些事情的提示。這是否可以通過Scala的現有類型系統的高級用法或通過編譯器插件來完成,或者我都不知道。
如以下注釋中所述,將結果稱爲「聯合類型」不適合此用例。我不知道還有什麼可以稱之爲的,但這是我目前最接近的想法。其他語言對這個想法有特別的支持嗎?這將如何在Coq和Agda工作?
對於我來說,命名這個問題並理解它的位置(類型理論,可判定性等等)對於我來說比對ANSWER
的工作實現更重要,儘管兩者都很好。獎金指向任何可以與Scalaz,Monoid或類別理論相關聯的人。
我不知道那個工會類型是去這裏的路。看起來好像你是在對一個HList表示的參數進行curried函數的摺疊式的事情之後。我認爲那樣的事情可能是可行的。無論如何,這是一個有趣的問題......如果我提出任何可行的方案,我會進行調查和回答。 –
哇 - 謝謝,Miles。我很想聽聽你對這個問題的看法。我同意工會類型本身似乎並不完全是這種情況下所要求的。 –
@MilesSabin我已經澄清了我的問題並提出了一些可能需要回答的表單。我還不清楚這是否應該成爲可能,但無論哪種方式,這對我來說都是一個很好的練習。 –