haskell - 为什么haskell不能推导出这个多参数类型类?
问题描述
我有两个类型类
class Concatable a where
empty :: a
(<+>) :: a -> a -> a
class Concatable b => Output a b where
out :: a -> b
和以下功能
nl :: (Output a AnsiDark) => [a] -> AnsiDark
nl a = foldr addNl empty a
where
addNl :: a -> AnsiDark -> AnsiDark
addNl ast org = doAddIf ast <+> org
doAddIf :: a -> AnsiDark
doAddIf ast = if out ast == sDedent
then out ast
else out ast <+> sNewline
( AnsiDark
implements Concatable
,sDedent
是一个类型的常量AnsiDark
)
以及启用了以下语言扩展(这甚至可能与问题无关,我对这些复杂类型相关的问题相当陌生)
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
我收到以下错误:
../src-hs/ANSITerm.hs:65:22: error:
• Could not deduce (Output a1 AnsiDark) arising from a use of ‘out’
from the context: Output a AnsiDark
bound by the type signature for:
nl :: forall a. Output a AnsiDark => [a] -> AnsiDark
at ../src-hs/ANSITerm.hs:59:1-44
• In the first argument of ‘(==)’, namely ‘out ast’
In the expression: out ast == sDedent
In the expression:
if out ast == sDedent then out ast else out ast <+> sNewline
我不太明白为什么 haskell 无法推断a
......我会求助于使用类型注释,out
就像这样
out @a @AnsiDark
但是类型注释似乎不适用于类型变量。那么......我的问题到底是什么?我该如何解决?
解决方案
nl :: (Output a AnsiDark) => [a] -> AnsiDark
...
where
doAddIf :: a -> AnsiDark
...
a
出现在这两行的s 是不一样的。就好像你写过:
nl :: (Output x AnsiDark) => [x] -> AnsiDark
...
where
doAddIf :: y -> AnsiDark
...
由于您正在使用out
indoAddif
您需要将Output
约束添加到其签名中(我相信如果您删除签名它将起作用,因为将推断出正确的签名)。
您可能还对ScopedTypeVariables
扩展感兴趣。启用此功能后,如果您编写
nl :: forall a. (Output a AnsiDark) => [a] -> AnsiDark
然后您可以在子句中的签名以及您尝试过的类型应用程序中引用它。 a
where
out @a @AnsiDark
推荐阅读
- c# - 显示整个 GridView 行的工具提示
- spring - 在 Spring Boot 应用程序中从外部 JAR 加载模型和 DAO
- excel - Excel VBA 循环优化 - j = 2 时退出
- r - 循环遍历 R 中后续行中的 NA 值
- maven - Maven项目中将java类导入Jsp
- c# - 从 Mac 上的 Rider 附加到 Azure Functions 的调试器
- python - 使用 Python 进行 Web 抓取:解析错误时出现意外的 EOF
- android - 使用 FirestoreRecyclerAdapter 的项目和类别
- java - 在 JList 中显示项目
- android - 在 okhttp3 中超时服务缓存