You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell中如何推断"(not .) . any"的类型?

关于Haskell中all/none/any实现的两个疑问

我正在通过Codewars学习Haskell,对应的题目要求实现all、none、any三个函数,参考实现代码如下:

module Codewars.Kata.AllNoneAny where

import Prelude hiding (all, any)

all, none, any :: (a -> Bool) -> [a] -> Bool
all  = (and .) . map
none = (not .) . any
any  = (or .) . map

疑问1

由于(.)是infixr 9优先级的右结合运算符,我认为应先组合(. any),再组合(not .),这个理解是否正确?

疑问2

如何将类型为(a -> Bool) -> a -> Bool的(not .)与类型为(([a] -> Bool) -> c) -> (a -> Bool) -> c的(. any)组合成类型为(a -> Bool) -> [a] -> Bool的(not .) . any?

相关类型定义:

not :: Bool -> Bool
(.) :: (b -> c) -> (a -> b) -> (a -> c)
any :: (a -> Bool) -> [a] -> Bool

(. any) :: (([a] -> Bool) -> c) -> (a -> Bool) -> c
(not .) :: (a -> Bool) -> a -> Bool
(not .) . any :: (a -> Bool) -> [a] -> Bool

解答

针对疑问1:理解错误,正确结合顺序是(not .)与any直接组合

(.)是右结合运算符,但这里的表达式结构是( (not .) ) . any——(not .)是一个完整的函数(可以理解为“接收一个返回Bool的函数,返回它的取反版本”),any是另一个独立函数。右结合的规则是针对连续的.链式组合(比如f . g . h会解析为f . (g . h)),但这里不存在嵌套组合(. any)的情况,你之前的拆分是错误的,不是not和(. any)组合,而是(not .)和any直接组合。

针对疑问2:通过函数组合的类型匹配规则推导

首先纠正一个小偏差:(not .)的实际类型应该是(x -> Bool) -> (x -> Bool),而非你标注的(a -> Bool) -> a -> Bool。(not .)等价于\f x -> not (f x),即接收一个返回Bool的函数f,返回一个新函数——先执行f再对结果取反。

现在推导(not .) . any的类型:

  1. any的类型是(a -> Bool) -> ([a] -> Bool):它接收一个谓词p :: a -> Bool,返回一个检查列表的函数check :: [a] -> Bool。
  2. (not .)的类型是(x -> Bool) -> (x -> Bool):它接收一个返回Bool的函数(比如上面的check),返回其取反版本\xs -> not (check xs)。
  3. 函数组合(.)的核心是匹配左函数的输入类型与右函数的输出类型:any的输出[a] -> Bool正好是(not .)的输入类型,因此组合后的函数逻辑是:
    • 先接收p :: a -> Bool,传给any得到check :: [a] -> Bool
    • 再把check传给(not .),得到\xs -> not (check xs)
    • 整体类型就是(a -> Bool) -> ([a] -> Bool),也就是(a -> Bool) -> [a] -> Bool,完全符合none的类型要求。

本质上(not .) . any等价于\p xs -> not (any p xs),和none的语义完全一致。


内容的提问来源于stack exchange,提问作者zichao liu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 18:23:26