[英]How to pass a generic function as parameter to another function?
假设我有三个功能:
data Foo = Foo { x :: String, y :: String, z:: String }
fooZero :: Foo
fooZero = Foo "empty" "empty" "empty"
fooOne :: String -> Foo
fooOne a = Foo a "empty" "empty"
fooThree :: String -> String -> String -> Foo
fooThree a b c = Foo (doSomething a) (doSomethingElse b) (doAnotherThing c)
现在,我希望能够在另一个函数中传递它们( f :: (???? -> Foo)
,仅在另一个昂贵的函数( evalSomething
)需要它的情况下才执行:
bar :: Int -> Int -> (???? -> Foo) -> Int
bar a b f = if (a == b) then a
else if (a > b) then evalSomething f -- return Int
else a + b
通过这种方式:
let one = "One"
let two = "Two"
let three = "Three"
bar 8 8 (fooZero)
bar 1 2 (fooOne one)
bar 5 3 (fooThree one two three)
我怎样才能做到这一点?
正如nm在评论中所说,您根本就不需要任何函数类型 –一阶类型bar :: Int -> Int -> Foo -> Int
可以很好地完成工作,因为您不需要实际上为foo
函数提供bar
任何参数-这些参数在应用bar
之前传递,即,您仅传递结果。 由于懒惰,因此foo
函数是否昂贵并不重要,因此您宁愿不对它们进行评估,如果不需要的话:Haskell将确保如果您实际上不需要它们,就不会评估函数结果!
一般来说, 有一种东西,可以让你“通过泛型函数作为参数”虽然。 这称为Rank-2多态性 。
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE UnicodeSyntax #-}
bar :: Int -> Int -> (∀ t . Monoid t => t -> Foo) -> Int
bar a b f
| a == b = a
| a > b = f (mempty :: [])
| otherwise = a + b
(如果你不是Unicode语法的球迷,你也可以写∀
为forall
。)实际上并不似乎是你想要的应用程序,但。
只需声明为:
bar :: Int -> Int -> Foo -> Int
bar a b f = if (a == b) then a
else if (a > b) then evalSomething f
else a + b
并将其称为:
bar 5 3 (fooThree one two three)
由于Haskell是惰性的,除非在evalSomething中需要fooThree,否则实际上不会对其进行评估。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.