[英]Haskell: Functions that sometimes return a function
How do you write a function that can either return a value or another function? 你如何编写一个可以返回值或其他函数的函数?
For example: 例如:
Function Foo (x)
If X = 0 Return "Done"
Else Return a Function that calls Foo(x-1)
In haskell the return type of a function can only depend on the type of its arguments and, in case of functions with polymorphic return types, how the return value is used. 在haskell中,函数的返回类型只能依赖于其参数的类型,并且在具有多态返回类型的函数的情况下,如何使用返回值。 In particular the return type of the function can not depend on the value of the argument.
特别是函数的返回类型不能取决于参数的值。
In other words: you can't do what you want directly. 换句话说:你不能直接做你想做的事。 In cases where you want to return one of two types, you can usually the type
Either ab
which is defined as data Either ab = Left a | Right b
在要返回两种类型的一种情况下,你通常可以在类型
Either ab
定义为data Either ab = Left a | Right b
data Either ab = Left a | Right b
, which allows you to return a value of type a
wrapped in a Left
or a value of type b
wrapped in a Right
. data Either ab = Left a | Right b
,它允许你返回类型的值, a
包裹在Left
或类型的值b
包裹在Right
。 You could then use pattern matching to retrieve the value in a type safe manner. 然后,您可以使用模式匹配以类型安全的方式检索值。
However since in this case the type for b
would have to be infinite this does not work and you have to define your own wrapper type for this. 但是,因为在这种情况下,
b
的类型必须是无限的,这不起作用,你必须为此定义自己的包装器类型。 Like so: 像这样:
data MyResult = Str String | Fun ( () -> MyResult)
foo 0 = Str "done"
foo x = Fun (\ () -> foo (x-1))
foo
now has type Num a => a -> MyResult
. foo
现在有类型Num a => a -> MyResult
。 However every time you call foo
you have to pattern match to see whether you got back a Str with a string inside or a Fun with a function inside. 但是每当你调用
foo
你必须进行模式匹配,看看是否有一个带有字符串的Str或者带有函数的Fun。
Also note that if you want to return a function rather than a value in order to delay execution, this doesn't make sense in haskell because it is lazy and things generally don't get evaluated before they are used. 还要注意,如果你想返回一个函数而不是一个值来延迟执行,这在haskell中没有意义,因为它是懒惰的,并且在使用之前通常不会对它们进行评估。
From the looks of your pseudo code, I'm guessing you're expecting to return a "nullary" function, that is one that takes no arguments, and will call 'Foo(x-1)' when invoked. 从伪代码的外观来看,我猜你期望返回一个“无效”函数,即不带参数的函数,并在调用时调用'Foo(x-1)'。
If this is so, then as pointed out at the end of sepp2k's answer, there is such need in Haskell - that is what happens by default. 如果是这样,那么正如sepp2k的答案结束时指出的那样,Haskell中存在这样的需求 - 这就是默认情况下会发生的事情。 Specifically:
特别:
foo x = if x == 0 then "Done"
else foo(x-1)
does exactly this: The value returned by calling, say, foo(7)
is a thing that when the program needs it's value will evaluate foo(6)
. 正是这样做的:通过调用,也就是说,返回的值
foo(7)
是一件事程序需要时,它的价值将评估foo(6)
The recursive call won't be evaluated inside the evaluation of the if
expression. 在
if
表达式的求值中不会评估递归调用。
You need to think about the types of your function: if Foo is of type (Int -> t), what is t? 你需要考虑函数的类型:如果Foo是类型(Int - > t),那么t是什么? It needs to return something of type t in both cases.
在两种情况下都需要返回t类型的东西。 I think this is a little hard, because I don't think t can be String type or a function type (->) in the same function.
我认为这有点难,因为我不认为在同一个函数中可以是String类型或函数类型( - >)。
I know this doesn't answer your question directly, but I think you need to expand your idea about what it means to "return a function". 我知道这不会直接回答你的问题,但我认为你需要扩展你对“返回一个函数”意味着什么的想法。 For example the function:
例如功能:
mean3 :: Float -> Float -> Float -> Float
mean3 x y z = (x + y + z) / 3
Can be thought of as "taking 3 numbers and returning a number". 可以被认为是“取3个数字并返回一个数字”。 Or it can be thought of as "a function taking two numbers, and returning a function from a number to a number":
或者它可以被认为是“一个函数取两个数字,并将一个函数从一个数字返回一个数字”:
mean3 :: Float -> Float -> (Float -> Float)
mean1 :: (Float -> Float)
mean1 = mean3 1 2
Just following up from sepp2k's great answer. 刚刚接受sepp2k的好回答。 I think you're missing a fundamental concept in Haskell - you're always returning a function.
我认为你在Haskell中缺少一个基本概念 - 你总是返回一个函数。 Even a "value" of sorts is a function.
甚至各种各样的“价值”也是一种功能。
For example, bust open ghci and try: 例如,胸围打开ghci并尝试:
> :t 5
:: (Num t) => t
Just a function that takes no input, return value is a Num. 只是一个不输入的函数,返回值是一个Num。
> :t "What is this?"
:: [Char]
Likewise, just a function that takes no value, returns [Char] 同样,只是一个没有值的函数,返回[Char]
"But these are all just values! I'm not convinced!" “但这些都只是价值观!我不相信!”
What's main then? 那么主要的是什么? (Supposing you've got it defined):
(假设你已定义):
> :t main
:: IO ()
Just a function that returns an IO () instance. 只是一个返回IO()实例的函数。
{-# LANGUAGE ExistentialQuantification #-}
data MyResult = Str String | forall a. Fun a -- deriving Show
foo 0 = Str "done"
foo x = Fun (\ () -> foo (x-1))
that sort of works, but you can't derive an existential type (methinks) so you need to call foo like that: (\\(Main.Str x) -> x) (Main.foo 0)
. 那种工作,但你不能导出一个存在类型(methinks)所以你需要像这样调用foo:
(\\(Main.Str x) -> x) (Main.foo 0)
。
If you know how to get Main module into focus in ghci please post a comment. 如果你知道如何让主模块成为ghci的焦点,请发表评论。
Normally, we write this as 通常,我们将其写为
foo _ = "Done"
or, pointlessly, 或者,毫无意义地,
foo = const "Done"
(Unless, of course, we really wanted to get _|_
for negative numbers ;-) (当然,除非我们真的想得到负数的
_|_
;-)
foo x =
if x<=0 then "Done"
else foo2 (x)
foo2 x = foo (x-1) ++ foo (x-1)
Found a non-trivial example. 找到了一个非平凡的例子。 This seems to work.
这似乎有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.