Haskell:有时返回函数的函数

Jon*_*len 6 haskell types functional-programming

你如何编写一个可以返回值或其他函数的函数?

例如:

Function Foo (x)
    If X = 0 Return "Done" 
    Else Return a Function that calls Foo(x-1)
Run Code Online (Sandbox Code Playgroud)

sep*_*p2k 21

在haskell中,函数的返回类型只能依赖于其参数的类型,并且在具有多态返回类型的函数的情况下,如何使用返回值.特别是函数的返回类型不能取决于参数的值.

换句话说:你不能直接做你想做的事.在要在其中返回两种类型中的一个的情况下,通常可以在类型Either a b,其定义为data Either a b = Left a | Right b允许,则返回类型的值a包裹在Left或类型的值b裹着Right.然后,您可以使用模式匹配以类型安全的方式检索值.

但是,因为在这种情况下,类型b必须是无限的,这不起作用,你必须为此定义自己的包装类型.像这样:

data MyResult = Str String | Fun ( () -> MyResult)
foo 0 = Str "done"
foo x = Fun (\ () -> foo (x-1))
Run Code Online (Sandbox Code Playgroud)

foo现在有了类型Num a => a -> MyResult.但是每次你打电话foo都要进行模式匹配,看你是否有一个带有字符串的Str或带有函数的Fun.

另请注意,如果要返回一个函数而不是一个值来延迟执行,这在haskell中没有意义,因为它很懒惰,并且在使用它们之前通常不会对它们进行求值.

  • @JonathanAllen:不仅没有共同的基本类型,也没有子类型. (11认同)
  • 虽然我应该补充一点,在许多情况下,你依赖于OO语言中的子类型,但是haskell的参数多态性允许你以不同的方式实现相同的效果. (9认同)
  • 更重要的是,没有检查值来确定其类型的一般方法.哪个是*好*的东西,因为这意味着我们可以确信多态函数对所有参数都表现一致. (5认同)
  • 那么没有统一的基类型,就像我们在.NET中一样,或者几乎没有Java? (3认同)
  • @camccann:java中的`foo instanceof Bar`是有意义的,当且仅当foo的静态类型是Bar的超类型时.否则它总是错误的.在haskell`foo instanceof Bar`将始终返回true(如果foo的静态类型为Bar)或总是返回false(如果不是).这些都不会有用.关键是在java中你不知道Object类型的变量是否真的包含String或ArrayList(作为示例).在haskell你总是知道类型,所以你不需要检查它. (3认同)
  • @JonathanAllen:如果我做'左边的情况x ......'我不期待x的类型.x的类型是`要么foo bar`,我知道,没有必要检查它.我正在检查x的内容.对于某种方式的变体类型也是如此,但变体可能包含一个void指针,您不会静态地知道它的类型.无论哪种方式,当我谈到"运行时类型检查"时,我讨论的是Java/C#意义上的反射,而不是"手工"的变通方法,这只是因为C你*不能*在运行时检查值的类型... (3认同)
  • 运行代码时,我得到以下内容.对于()作为参数也是如此.我究竟做错了什么?'发生检查:无法构造无限类型:b = a - > [Char] b预期类型:[Char] b推断类型:[Char](a - > [Char] b)在表达式中:右(\ x - > foo(x - 1))在`foo'的定义中:foo x = Right(\ x - > foo(x - 1))失败,模块加载:无. (3认同)