Haskell 对啥不满意?它在抱怨我的类型签名

Posted

技术标签:

【中文标题】Haskell 对啥不满意?它在抱怨我的类型签名【英文标题】:What is Haskell not happy about? It's complaining about my type signatureHaskell 对什么不满意?它在抱怨我的类型签名 【发布时间】:2012-12-16 12:05:47 【问题描述】:

我的 Haskell 有另一个问题。我从一个问题中得到了以下数据构造函数,

type Point = (Int, Int)

data Points = Lines Int Int
            | Columns Int Int
            | Union Points Points
            | Intersection Points Points

它是关于从 (0,0) 和 (x,y) 开始的网格上的点,其中 x 为与原点的水平距离,y 为与原点的垂直距离。

我试图从中定义一个函数“Lines”,给定 Lines x y 将评估网格上垂直距离为 x ~ y 的所有点。 例如

> Lines 2 4 
(0,2)(1,2)(2,2)(3,2)....
(0,3)(1,3)(2,3)(3,3)....
(0,4)(1,4)(2,4)(3,4)....

等等。好吧,我所做的是,

Lines :: Int -> Int -> Points
Lines lo hi = [ (_, y) | lo <= y && y <= hi ]

但 Haskell 抱怨说;

无效的类型签名 Lines :: Int -> Int -> Points。 应该是::

这是什么意思? “Points”已经在上面定义了......肯定“Int”“Points”被视为“类型”吗?没看出问题,为什么Haskell会糊涂?

【问题讨论】:

lines 中的 x 值从何而来?你想构建一个无限列表的列表吗?然后尝试lines' lo hi = map (\y -&gt; map (\x -&gt; (x, y)) [0..]) [lo..hi]。请注意,已经有一个名为 lines 的函数。 【参考方案1】:

    函数不能以大写字母开头。所以你需要使用lines,而不是Lines。这可能是您看到的错误消息的来源。

    语法[ ... ] 用于创建结果的列表,但您的类型签名声称该函数返回Points,这不是任何类型的列表。如果您要返回 Point 值的列表,那就是 [Point] 类型。

    我真的不知道你对Lines 的实现甚至试图做什么。语法对我来说毫无意义。


好的,所以考虑到你的 cmets...

您可以通过编写[lo .. hi] 来生成lohi 之间的数字列表。

您说 X 中可以包含“任意”值,但您需要准确确定其含义。您的示例似乎建议您永远想要从 0 向上的数字。生成该列表的方法是[0 .. ]。 (不给出上限会使列表无穷无尽。)

您的示例建议您需要一个列表列表,内部列表包含所有具有相同 Y 坐标的点以及所有可能的 X 坐标。

所以这是一种可能的方法:

type Point = (Int, Int)

lines :: Int -> Int -> [[Point]]
lines lo hi = [ [(x,y) | x <- [0..]] | y <- [lo .. hi] ]

这可能有点难以阅读,所有这些开括号和右括号,所以也许我可以让它稍微干净一点:

lines lo hi =
  let
    xs = [0..]
    ys = [lo .. hi]
  in [    [(x,y) | x <- xs]    | y <- ys]

如果你运行它,你会得到

> lines 2 4
[[(0,2), (1,2), (2,2), ...],
[(0,3), (1,3), (2,3), ...],
[(0,4), (1,4), (2,4), ...]]

换句话说,外部列表有 3 个元素(Y=2、Y=3 和 Y=4),并且三个内部列表中的每一个都是无限长的(每个可能的正 X 值)。

【讨论】:

您好,感谢您的回答!好的,我将尝试将大写字母固定为小写...>Lines 只是尝试生成一组给定 lo,hi 的点 (Int,Int)。 (_,y) 表示任意数字进入 x 条目,并且 y 大于或等于 lo,小于或等于 hi。至少那是我的意图……我一生中从未做过编程,我对自己的技能真的很不自信…… @Brad 列表理解语法基本上是xs = [val | val &lt; someList, boolean guards]。在英语中,xs 是一个值列表,每个值都从一个名为someList 的列表中提取,过滤掉任何未通过布尔保护的值。 Haskell 不会神奇地为您发明值,您必须明确指定 x 而不是使用下划线,并且您必须指定基本列表。所以也许lines lo hi = [ (1,y) | y &lt;- [1..], y &gt;= lo, y &lt;= hi]. 我敢打赌真正想要的是lines lo hi = [(x, y) | y &lt;- [0..], x &lt;- [lo..hi]]。 (注:单层列表,转置迭代顺序)

以上是关于Haskell 对啥不满意?它在抱怨我的类型签名的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Haskell 没有在函数签名中推断数据类型的类型类?

`undefined` 的类型签名在 Haskell 中是啥意思?

为啥我的 Haskell 函数参数必须是 Bool 类型?

如何从类型重建 Haskell 表达式

Rust闭包和Haskell lambda有什么区别? [关闭]

在 Haskell 中编写 AI Solver 时的类型变量不明确