这里还是一个Haskell新手.我知道这足以让我自己陷入错误假设的困境.如果我有以下功能......
quadsum w x y z = w+x+y+z
Run Code Online (Sandbox Code Playgroud)
我想要一个可以获取列表的函数,将每个元素用作指定函数中的参数quadsum,并返回一个curried函数供以后使用.
我一直在努力尝试......
magicalFunctionMaker f [] = (f)
magicalFunctionMaker f (x:xs) = magicalFunctionMaker (f x) xs
Run Code Online (Sandbox Code Playgroud)
希望能够做到这一点......
magicalFunctionMaker (quadsum) [4,3,2]
Run Code Online (Sandbox Code Playgroud)
获得像...这样的咖喱功能:
(((quadsum 4) 3) 2)
Run Code Online (Sandbox Code Playgroud)
或者,或者,致电:
magicalFunctionMaker (quadsum) [4,3,2,1]
Run Code Online (Sandbox Code Playgroud)
导致...
((((quadsum 4) 3) 2) 1)
Run Code Online (Sandbox Code Playgroud)
这可能吗?我是多么误导?
我认为你误解了Haskell类型系统.
首先,你的"quadsum"功能已经过去了.您可以编写"quadsum 4 3"并返回一个函数,该函数期望2和1作为额外参数.当你写"quadsum 4 3 2 1"相当于"((((quadsum 4)3)2)1)"时.
在Haskell中,整数列表具有与整数或元组不同的类型,例如"(4,3,2,1)".鉴于此,很难理解你想要做什么.如果你写这个应该发生什么?
magicalFunctionMaker quadsum [5,4,3,2,1]
Run Code Online (Sandbox Code Playgroud)
你的"magicalFunctionMaker"看起来很像"foldl",除了你给foldl的函数只有两个参数.所以你可以写:
mySum = foldl (+) 0
Run Code Online (Sandbox Code Playgroud)
这将返回一个获取列表并对元素求和的函数.
(顺便说一句,一旦你了解了这一点,了解foldl和foldr之间的区别.
编辑:
重新阅读你的问题,我想你正试图得到:
magicalFunctionMaker quadSum [4,3,2,1] :: Integer
magicalFunctionMaker quadSum [4,3,2] :: Integer -> Integer
Run Code Online (Sandbox Code Playgroud)
这是不可能的,因为magicalFunctionMaker的类型将取决于list参数的长度,这意味着动态类型.正如有人所说,多变量函数可以做一些接近这个的事情(尽管没有列表参数),但是这需要相当多的类型hackery的milli-olegs.
保罗·约翰逊的回答几乎涵盖了这一点。做就是了
quadsum 4 3 2
Run Code Online (Sandbox Code Playgroud)
结果将是您想要的函数,类型为Integer -> Integer。
但有时这还不够好。有时您会得到数字列表,但您不知道列表有多长,并且需要将这些元素应用到您的函数中。这个有点难。你不能这样做:
magicalFunction2 f [] = f
magicalFunction2 f (x1:x2:xs) = f x1 x2
Run Code Online (Sandbox Code Playgroud)
因为结果有不同的类型。在第一种情况下,结果需要两个参数,而在第二种情况下,它是一个完全应用的函数,因此不允许使用更多参数。在这种情况下,最好的办法是保留列表和原始函数,直到有足够的参数可用:
type PAPFunc f a result = Either (f, [a]) result
magicfunc f xs = Left (f,xs)
apply (Left (f,xs)) ys = Left (f,xs++ys)
apply p _ = p
simp2 :: PAPFunc (a->a->b) a b -> PAPFunc (a->a->b) a b
simp2 (Left (f,(x1:x2:xs))) = Right (f x1 x2)
simp2 p = p
Run Code Online (Sandbox Code Playgroud)
现在你可以这样做:
Main> let j = magicfunc (+) []
Main> let m = apply j [1]
Main> let n = apply m [2,3]
Main> either (const "unfinished") show $ simp2 m
"unfinished"
Main> either (const "unfinished") show $ simp2 n
"3"
Run Code Online (Sandbox Code Playgroud)
每个数量都需要一个单独的简化函数,这个问题最容易通过 Template Haskell 解决。
在 Haskell 中使用参数列表(而不是列表参数)往往非常尴尬,因为多个结果都有不同的类型,并且很少支持具有可变数量的不同类型参数的集合。我见过三大类解决方案:
分别为每种情况显式编码(很快就会变得很多工作)。
哈斯克尔模板。
类型系统黑客攻击。
我的回答主要涉及如何减少痛苦。2和3不适合胆小的人。
编辑:事实证明,Hackage 上有一些 与此问题相关的软件包。使用“迭代者”:
import qualified Data.Iteratee as It
import Control.Applicative
magic4 f = f <$> It.head <*> It.head <*> It.head <*> It.head
liftedQuadsum = magic4 quadsum
-- liftedQuadsum is an iteratee, which is essentially an accumulating function
-- for a list of data
Main> p <- It.enumChunk (It.Chunk [1]) liftedQuadsum
Main> It.run p
*** Exception: EofException
Main> q <- It.enumChunk (It.Chunk [2,3,4]) p
Main> It.run q
10
Run Code Online (Sandbox Code Playgroud)
但“iteratee”和“enumerator”可能有点矫枉过正。
| 归档时间: |
|
| 查看次数: |
11206 次 |
| 最近记录: |