Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 哈斯凯尔推导出了过于严格的类型_Haskell_Type Inference - Fatal编程技术网

Haskell 哈斯凯尔推导出了过于严格的类型

Haskell 哈斯凯尔推导出了过于严格的类型,haskell,type-inference,Haskell,Type Inference,免责声明:我刚刚开始学习Haskell,我不确定“严格”这个词是否正确 我试图缩小我的问题范围,但我无法真正找到问题所在,因此这里是我的代码,无法编译: module Json where import Data.List (intersperse) data JNode = JObject [(String, JNode)] | JArray [JNode] | JString String | JNumber Double | JBool Bool |

免责声明:我刚刚开始学习Haskell,我不确定“严格”这个词是否正确

我试图缩小我的问题范围,但我无法真正找到问题所在,因此这里是我的代码,无法编译

module Json where
import Data.List (intersperse)

data JNode = 
    JObject [(String, JNode)]
  | JArray  [JNode]
  | JString String
  | JNumber Double
  | JBool   Bool
  | JNull

instance Show JNode where
  show = show_node 0 where
    glue = foldl (++) ""
    show_tabs n              = glue $ take n $ repeat "  "
    show_list n              = glue . intersperse ",\n" . map (show_pair (n + 1))
    show_sect n l r xs       = glue ["\n", tabs, l, "\n", show_list n xs, "\n", tabs, r] where tabs = show_tabs n
    -- show_pair :: (Show a) => Int -> (a, JNode) -> String -- works when uncommented
    show_pair n (name,  val) = glue [show_tabs n, show name, " : ", show_node n val]
    show_node n (JObject xs) = show_sect n "{" "}" xs
    show_node n (JArray  xs) = show_sect n "[" "]" $ zip [0..] xs
    show_node n (JString x ) = show x
    show_node n (JNumber x ) = show x
    show_node n (JBool   x ) = show x
    show_node n (JNull     ) = "null"
错误是:

Prelude>:l scripts\json.hs
[1/1]编译Json(scripts\Json.hs,解释)
scripts\json.hs:21:59:
没有(枚举字符串)的实例
由算术序列“0..”产生
在“zip”的第一个参数中,即“([0..])”
在“($)”的第二个参数中,即“zip([0..])xs”
在表达式中:show_sect n“[”“]”“$zip([0..])xs
scripts\json.hs:21:60:
没有由文字“0”产生的(Num String)实例
在表达式中:0
在'zip'的第一个参数中,即'[0..]'
在“($)”的第二个参数中,即“zip[0..]xs”
失败,已加载模块:无。
查看带有注释的代码行。显然,当没有类型声明时,它要求我传递
String
,而不仅仅是
Show a
。有趣的是,当我甚至不使用它时,它仍然要求
名称
成为
字符串
,例如,当用以下内容替换
show\u pair
实现时:

show_pair n (name,  val) = show_node n val
有人能给我解释一下为什么它是这样工作的吗


我的代码的简化版有相同的问题,以防有人想改进答案:

data TFoo = 
    FooStr (String, TFoo)
  | FooNum (Int,    TFoo)

-- show_pair :: (a, TFoo) -> String
show_pair (_,    val) = show_node val
show_node (FooStr  x) = show_pair x
show_node (FooNum  x) = show_pair x

我想你希望
[0..]
被认为是
[Int]
,而事实似乎并非如此。这可能是因为
show_node
for
JObject
[(String,JNode)]
作为与
JArray
相同的参数传递到
show_sect

尝试仅在与数组元素一起压缩的表达式
[0..]
上强制键入:
zip([0..]:[Int])xs
。我相信问题在于
show\u sect
的推断类型


我强烈建议提供一些类型注释,我认为这样做是一个很好的实践。不过,我不太熟悉Haskell中的类型推断;dr:当您希望某些内容具有多态性时,请始终使用显式签名


在中(这是Haskell的类型系统所基于的),用于多态性的每个类型变量都需要通过类型级别lambda/for all显式地量化到范围中(∀). 所以事实上你需要

show_pair :: ∀ a. (Show a) => Int -> (a, JNode) -> String
可以说Haskell也需要这个,但它没有。它只是量化了您在显式签名†中提到的任何变量,所以您可以简单地编写

show_pair :: (Show a) => Int -> (a, JNode) -> String
此外,它还尝试在没有签名的顶级绑定中引入尽可能多的类型变量&ddagger

但是,它不会自动将任何类型变量引入本地绑定。因为编译器确切地知道在哪里使用
show\u pair
,所以它至少有一个您需要的类型实例化的完整上下文。它假设您只需要一个实例化。因此它会尝试推断mono的某种类型Simulic SuxPix,并且失败。仅通过添加显式签名,就迫使编译器考虑多态性签名。正如评论中所述,这并不是真的,因为自从GHC-7.0以来,有一个东西叫本地绑定,即使没有签名也没有多态性。我不知道这是对的。默认情况下。-即使可以省略签名,多态函数也应该更好地使用它们


†前提是您尚未使用扩展名
-XScopedTypeVariables
在更高的范围内引入该变量


‡不幸的是,这个使它非常难以依赖。

蛇壳
在Haskell中通常不使用,
camelCase
是最坚持的命名风格。我强烈建议将所有这些本地函数分解到顶层,并给每个函数一个类型签名。您不需要从模块中导出它们,但整个混乱将更易于阅读和处理。更一般地说,当您出现类型错误并且不知道问题出在哪里时,添加一些类型签名通常会帮助您获得更多有用的错误消息。在某些情况下,为本地绑定提供类型签名需要
ScopedTypeVariables
扩展。我不认为这里就是这种情况,但我怀疑你的函数最好是分解成碎片。我在写Haskell时学到的一件事(这反映了上面的评论):如果有疑问,请添加签名!准确地告诉它您希望限制猜测的内容。大多数情况下,猜测类型可能非常好,但提供帮助将始终对您有益!顺便说一句,
foldl(++)“
是连接字符串的一种非常低效的方法。快速的方法是
foldr(++)”
,或者,概括到列表,
foldr(++)[]
,更好地称为
concat
。为什么不让泛化抓住这一点呢?@dfeuer我想这是因为相互递归。泛化发生在整个相互递归定义组中,但为时已晚。@chi,我想这就是
RelaxedPolyRec
或任何它被称为的东西的意义所在?或者这也是最重要的仅限级别?这里的标准似乎有点过于繁琐。无论如何,我是一个痴迷于类型签名编写的阵营,害怕库会让我感到痛苦。很确定这是因为多态递归,如果没有
RelaxedPolyRec
,情况会更糟:那么所有函数都需要签名。本地绑定hing是
单眼绑定
,如果您启用此代码,则即使在
show\u pair
上签名,此代码也无法工作。此答案的最后一段是m