也许你还没有为函数应用足够的参数?

Dav*_*aya 6 haskell

我正在大学的课程中学习Haskell,并且有一个考试练习,我们需要定义一个函数,它接受一个函数列表 [(Int ->Int)]和一个Type的另一个参数Int并返回一个Int.所以类型应该是

compose :: [(Int ->Int)] -> Int -> Int.
Run Code Online (Sandbox Code Playgroud)

该函数应从左到右返回列表中函数的组合,并将其应用于第二个参数.我尝试了以下方法:

compose :: [(Int -> Int)] -> Int -> Int
compose [] x = x
compose (f:fs) x  
    |fs == [] = f x
    |f  : (compose fs x)
Run Code Online (Sandbox Code Playgroud)

但编译器抛出一个错误:

003Exam.hs:24:22:
    Couldn't match expected type ‘Int’ with actual type ‘[Int -> Int]’
    In the expression: f : (compose fs x)
    In an equation for ‘compose’:
        compose (f : fs) x
          | fs == [] = f x
          | otherwise = f : (compose fs x)

003Exam.hs:24:28:
    Couldn't match expected type ‘[Int -> Int]’ with actual type ‘Int’
    In the second argument of ‘(:)’, namely ‘(compose fs x)’
    In the expression: f : (compose fs x)
Run Code Online (Sandbox Code Playgroud)

如果我离开最后一行,例如:

compose :: [(Int -> Int)] -> Int -> Int
compose [] x = x
compose (f:fs) x  
    |fs == [] = f x
Run Code Online (Sandbox Code Playgroud)

然后我也得到一个错误 - 这是我真正不理解的错误:

003Exam.hs:23:13:
    No instance for (Eq (Int -> Int))
      (maybe you haven't applied enough arguments to a function?)
      arising from a use of ‘==’
    In the expression: fs == []
    In a stmt of a pattern guard for
               an equation for ‘compose’:
      fs == []
    In an equation for ‘compose’: compose (f : fs) x | fs == [] = f x
Run Code Online (Sandbox Code Playgroud)

如果有任何帮助澄清我做错了什么,我会很高兴.

Zet*_*eta 6

首先,(:)仅用于在列表的前面添加元素(或模式匹配那些元素),因此您必须替换

f : compose fs x
Run Code Online (Sandbox Code Playgroud)

f (compose fs x)
Run Code Online (Sandbox Code Playgroud)

接下来,您必须Bool在防护中使用类型或模式匹配的表达式:

| fs == []  = -- this line is still wrong, see below
| otherwise = f (compose f xs)
Run Code Online (Sandbox Code Playgroud)

但是,没有Eq功能实例.两个函数的等价性是不可判定的(通常),因此使用null :: [a] -> Bool而不是(==) :: Eq a => [a] -> [a] -> Bool:

compose :: [(Int -> Int)] -> Int -> Int
compose [] x = x
compose (f:fs) x  
  | null fs   = f x
  | otherwise = f (compose fs x)
Run Code Online (Sandbox Code Playgroud)

既然compose [] xx你甚至可以删除支票相同:

compose :: [(Int -> Int)] -> Int -> Int
compose []     x = x
compose (f:fs) x = f (compose fs x)
Run Code Online (Sandbox Code Playgroud)

演习

  • 扩展compose [(+1), (+2)] 1(用它的定义替换它)而不去掉中间术语.你注意到一个模式吗?
  • 这种模式是否会提醒您库函数?
  • 尝试使用该库函数来编写compose.