类型签名困惑:Haskell中choose函数的类型匹配疑问
解惑:Haskell多态函数
choose为何能接受带约束的运算符 你的困惑核心在于对Haskell多态类型变量的理解——choose的类型参数a可以匹配带类型约束的函数类型,而非只能匹配无约束的简单类型。下面一步步拆解:
1. 先明确choose的多态本质
choose的类型签名是:
choose :: Player -> a -> a -> a
这里的a是多态类型变量,它可以代表任意类型——包括像Num b => b -> b -> b这种带约束的函数类型,而不是你误以为的只能是a -> a -> a这种无约束的函数类型。
2. 调用时的类型实例化
当你执行choose p (+) (-)时,Haskell会自动将choose的类型参数a实例化为Num b => b -> b -> b(用b是为了和原类型的a区分,避免混淆)。此时choose的实际类型变为:
choose :: Player -> (Num b => b -> b -> b) -> (Num b => b -> b -> b) -> (Num b => b -> b -> b)
这个类型完全匹配(+)和(-)的签名,因为它们本身就是Num b => b -> b -> b——能接受任意Num类型的两个参数,返回同类型结果。
3. 你设想的类型和实际类型的区别
你以为choose需要写成:
choose :: Num a => Player -> (a -> a -> a) -> (a -> a -> a) -> (a -> a -> a)
但这个版本的choose会被限制为只能处理针对某个具体Num类型的函数(比如Int -> Int -> Int或Double -> Double -> Double),而原版本的choose可以处理多态的函数(即能适配所有Num类型的通用运算符),通用性更强。
4. 验证实例化后的类型
在GHCi中执行:t choose 'X' (+) (-),会得到:
choose 'X' (+) (-) :: Num b => b -> b -> b
这直观证明了choose返回的是一个多态函数,之后传入5 5时,b会被实例化为具体的数值类型(比如Integer),最终执行对应的运算。
内容的提问来源于stack exchange,提问作者William Boulanger
相关产品推荐
相关产品推荐

