Haskell中safeSearch传入空列表为何出现编译报错?
Haskell中safeSearch空列表调用的编译错误原因
问题背景
手动实现了替代length的count函数(可正常运行),以及根据索引取元素的search函数:
search [] _ = error "index too large" search (a:_) 0 = a search (_:a) b = search a (b - 1)
接着编写了safeSearch函数,要求索引越界或列表为空时返回Nothing,否则返回Just包裹的元素:
safeSearch :: [a] -> Int -> Maybe a safeSearch a b | b < 0 || b >= count a = Nothing | otherwise = Just (search a b)
非空列表调用正常,但执行main = print(safeSearch [] 5)时出现编译错误:
main.hs:91:8: error: * Ambiguous type variable `a0' arising from a use of `print' prevents the constraint `(Show a0)' from being solved. Probable fix: use a type annotation to specify what `a0' should be. These potential instances exist: instance Show Ordering -- Defined in `GHC.Show' instance Show Integer -- Defined in `GHC.Show' instance Show a => Show (Maybe a) -- Defined in `GHC.Show' ...plus 22 others ...plus 13 instances involving out-of-scope types (use -fprint-potential-instances to see them all) * In the expression: print (safeSearch [] 5) In an equation for `main': main = print (safeSearch [] 5) | 91 | main = print(safeSearch [] 5) | ^^^^^^^^^^^^^^^^^^^^^^ exit status 1
错误原因与解决方法
这个错误和safeSearch的逻辑无关,本质是Haskell的类型推断问题:
- 空列表
[]的类型是[a],这里的类型变量a没有任何具体的类型约束; print函数要求参数必须实现Show类型类,而Maybe a的Show实例依赖于a本身实现Show;- 编译器无法从空列表推断出
a的具体类型(因为空列表里没有任何元素能提供类型线索),所以出现了“类型变量歧义”的错误。
解决方法很简单,给表达式添加类型注解明确a的具体类型即可,比如:
-- 方式1:给空列表指定类型 main = print (safeSearch ([] :: [Int]) 5) -- 方式2:给整个safeSearch调用结果指定类型 main = print (safeSearch [] 5 :: Maybe Int)
这样编译器就能确定a是Int(Int自带Show实例),编译通过后会正常输出Nothing。
内容的提问来源于stack exchange,提问作者Louis FELDMAR
相关产品推荐
相关产品推荐

