【问题标题】:How to interpret this Haskell code that type checks?如何解释这个类型检查的 Haskell 代码?
【发布时间】:2017-07-22 20:08:19
【问题描述】:

学习Haskell Programming from First Principles这本书,我在第6章“类型类”中遇到了以下练习:

-- Hint: use some arithmetic operation to
-- combine values of type 'b'. Pick one.
arith :: Num b => (a -> b) -> Integer -> a -> b
arith = ???

我想出了以下解决方案,我称之为“解决方案”,因为它可以编译:

arith f _ x = f x

但我有点困惑如何“解释”我刚刚在上面写的内容。我对arith 类型签名的“解读”如下:

arith 接受一个函数,一个Integer,一个a 类型的参数, 并返回b 类型的结果;此外,该功能 arith 作为第一个参数是一个函数,它接受一个 a 类型的参数并返回 b 类型的值,并且该值 必须是 b 类型,其类型类是(或“约束”)Num

在那之后,我想出了上面的'解决方案',但我没有使用“一些算术运算来组合'b'类型的值”。不知何故,我认为“提示”具有误导性,或者完全没问题,我错过了一些东西,如果是这样,那我错过了什么?

【问题讨论】:

  • 嗯,这肯定不是预期的解决方案。您不仅不使用一些算术运算,而且完全忽略了整数参数。预期的解决方案实际上可能是我自己不确定。确实有很多完全不同的可能方法。
  • 确实,通常可以从类型信息派生一个实现,但这并不是一个很好的例子——Num 太模糊了,使用Integer 你可以做到 任何东西。我真的认为他们应该重新考虑这项工作。
  • 作为一个具体示例,您可以将(+) 应用于Integer 参数和f x,因为这两个值的类型都是Num 的实例。没有正确答案,只有很多很多有效答案。
  • @leftaroundabout 我不确定我是否完全同意Num 过于模糊。在某种程度上,它相当“强大”,也就是说,你可以用 b 做的事情是非常有限的。 Num有一个fromInteger,将Integer参数连接到b,然后就可以使用三个二元运算+, -, *了。
  • @EmreSevinç 你可以通过对自己施加额外的限制来增加练习的难度:使用等号右侧的所有参数。 (您当前的解决方案忽略了第二个论点。还有其他解决方案忽略了其他论点——后续练习也可能是尝试找到其中的一些。)总的来说,我认为这个特定的练习太模糊了,不能成为一个好的练习—— - 正是因为你现在感到的那种困惑。不是你;是书。

标签: haskell typeclass


【解决方案1】:

我认为预期的解决方案是:

arith f i a = f a + fromInteger i

或者将+ 替换为-*

回顾一下需求:在本练习中,您必须实现一个函数:

  1. 匹配类型签名arith :: Num b => (a -> b) -> Integer -> a -> b

  2. 使用算术运算来组合 b 类型的值。

您将获得三个类型的值 (a -> b)Integera。作为第一步,您需要将它们转换为b 类型的两个值。您可以通过将(a -> b) 应用到a 来获得第一个。然后你就剩下Integer 类型的值了。当您notice 类型类Num 的实例支持函数fromInteger :: Integer -> a 时(其中类型a 是我们定义的函数上下文中的b 类型),很明显您可以获得@987654339 类型的第二个值@ 通过将 fromInteger 应用于您的 Integer 值。第二步,使用Num 类型类中定义的算术运算之一组合b 类型的两个值。

【讨论】:

  • 感谢您和以上所有其他评论员为我提供了更深刻的理解。 PS:我也曾尝试过fromInteger 一段时间,试图想出一个解决方案,但不知何故仍然感到困惑,与上面所有的 cmets 一起度过了更多的时间真的很有帮助!
猜你喜欢
  • 2014-05-18
  • 1970-01-01
  • 2023-04-03
  • 2010-12-18
  • 2011-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多