在 lambda 函数中定义类型

meh*_*ix_ 0 lambda haskell

有什么方法可以为 lambda 函数的输入变量定义类型。我把它作为一个函数

bstar :: Language -> Int -> Language
bstar l n =
    case l of
    [] -> zero
    l -> case n of
            0 -> [[]]
            n -> (\pow l n -> if n == 0 
                              then [[]] 
                              else l `cat` (pow l (n-1))) l n `uni` (bstar l (n-1))
Run Code Online (Sandbox Code Playgroud)

当我在 haskell 中编译它时,出现类型错误“Int”与“String”不匹配。我想知道是否有任何方法可以将 lambda 函数“pow”l 的输入变量定义为语言。任何想法?

GS *_*ica 5

您可以使用ScopedTypeVariables语言扩展来启用此语法:

\(x :: Int) -> x
Run Code Online (Sandbox Code Playgroud)

-XScopedTypeVariables您可以在 GHC 命令行上启用扩展,或者通过输入

{-# LANGUAGE ScopedTypeVariables #-}
Run Code Online (Sandbox Code Playgroud)

在源文件的顶部。

正如我在对该问题的评论中指出的那样,这实际上可能无助于解决您的错误。对于许多简单的 Haskell 代码(包括您的代码),添加类型签名实际上不会对代码进行类型检查(否则不会进行类型检查)。它将做的是使定位类型错误变得更加容易,因为您会清楚您的意图和编译器推断的不同之处。

编辑以下评论中的讨论:

您的代码的问题在于您试图pow仅使用 lambda 定义递归函数,这是直接不可能的。您的 lambda需要一个函数pow作为参数,但您没有传递一个函数。

正如 @chi 的回答和评论所指出的,使用子句您的代码可能会最干净,但是如果您确实想保留内联 lambda,where您也可以这样做。fix

它具有以下类型和定义:

fix :: (a -> a) -> a
fix f = let x = f x in x
Run Code Online (Sandbox Code Playgroud)

在这种情况下,a类型将是您的函数所需的类型pow,即(Language -> Int -> Language)。因此fix最终会将您的 lambda 变成递归定义 -x在对应fix于您的pow.

bstar :: Language -> Int -> Language
bstar l n =
    case l of
    [] -> zero
    l -> case n of
            0 -> [[]]
            n -> fix (\pow l n ->
                          if n == 0 
                              then [[]] 
                              else l `cat` (pow l (n-1))) l n `uni` (bstar l (n-1))
Run Code Online (Sandbox Code Playgroud)

您可能需要将其添加到模块顶部的导入中:

import Data.Function (fix)
Run Code Online (Sandbox Code Playgroud)

您可以查看此问题以获取更多讨论fix