编写将输入函数作用于自身的run函数时出现无限类型错误
错误原因
你写的run函数抛出无限类型错误的核心是类型不匹配:
- 你给出的类型签名
run :: (t1 -> t2) -> t2约定了入参a是一个参数类型为t1、返回类型为t2的函数 - 函数体
a a要求a同时作为函数和该函数的入参,这就意味着入参a的类型必须等于t1,推导可得等式t1 ~ (t1 -> t2) - 这个等式要求
t1是一个包含自身的无限递归类型,Haskell标准类型系统默认不支持这类无限类型,因此直接抛出编译错误。
另外你原设想的「接收任意函数作为输入,返回该函数作用于自身的结果」本身逻辑上不可行:不是所有函数都能接收自身作为入参,比如Int -> Bool类型的函数,只能接收Int类型的输入,不可能把自身(函数类型)作为参数传入。
实现方案
如果你确实需要实现自应用的逻辑,可以通过自定义递归类型绕开无限类型限制:
- 先定义递归包装类型,把可以接收自身作为参数的函数包装起来
import Data.Typeable -- 仅示例需要,用来打印类型 newtype SelfFunc a = Wrap { unwrap :: SelfFunc a -> a }
- 重新实现
run函数
run :: SelfFunc a -> a run f = unwrap f f
- 调用示例
-- 示例1:传入返回固定值的包装函数 constWrap :: SelfFunc Int constWrap = Wrap (\_ -> 1024) -- 调用 run constWrap 输出 1024 -- 示例2:传入获取类型信息的包装函数 selfApplyWrap :: SelfFunc String selfApplyWrap = Wrap (\f -> "调用成功,当前输入类型是:" ++ show (typeOf f)) -- 调用 run selfApplyWrap 会输出对应的类型信息
内容的提问来源于stack exchange,提问作者A-P
相关产品推荐
相关产品推荐

