繁体   English   中英

具有不同类型参数的Haskell函数

[英]Haskell functions with parameters different types

正如问题所指出的,我在定义具有不同类型参数的函数时遇到了一些麻烦。 (Num数组,两个参数Int和返回Int)。

这是函数标题:

_sum_divide :: (Num a) => [a] -> (Int b) => b -> b -> b

我收到这个错误,我无法弄清楚

`Int' is applied to too many type arguments
In the type signature for `_sum_divide':
  _sum_divide :: Num a => [a] -> Int b => b -> b -> b

很抱歉出现这个愚蠢的错误,我是Haskell的菜鸟。

谢谢,祝您有个愉快的一天/晚上。

这似乎是类型类类型概念之间的基本混淆。 OO语言将所有这些都放在一起,但是在Haskell中,它们是根本不同的东西。

  • 类型是一组值 例如,类型Bool包含值FalseTrue 类型Int包含值01 ... 9223372036854775807及其负面影响。

  • 类型类是一组类型 例如,如果仅定义instance Num T ,则Num类包含Int类型, Double类型, Rational ...类型以及您自己的任何T类型。

通常,仅通过命名类型即可在函数签名中使用类型 例如,

foo :: [Int] -> [Int]
foo = map (*3)

是一个接受Int数字列表(即Int类型的值)的函数,并给出另一个这样的列表作为结果(其中每个条目都增加了三倍)。

foo的签名完全没有约束。 我实际上可以添加一个

foo :: Num Int => [Int] -> [Int]

这将表示该函数需要Int作为Num类的实例才能工作。 好吧,它确实需要能够计算*3 ,但是约束是多余的,因为我们知道 IntNum实例,编译器并不会忘记这一点。

约束真正有用的地方是多态函数。 例如,以下函数将数字列表中的每个条目增加三倍,而不管数字具有哪种特定类型

foo :: Num n => [n] -> [n]
foo = map (*3)

这种带有类型变量(例如a )的表示法实际上是

foo :: ∀ n . Num n => [n] -> [n]

含义, 所有数值类型n ,功能foo映射列表n -值对的列表n -值。

重要的是,约束是完全独立的从签名的实际类型规范。 例如,要为多态函数[a] -> b -> b -> b a应该是Num实例, b应该是Integral实例(整数类型的类,其中包含Int ),您可以d写

sum_divide :: (Num a, Integral b) => [a] -> b -> b -> b

另外,如果您真的是说Int ,那只是一个单一类型,没有理由为此引入类型变量

sum_divide :: Num a => [a] -> Int -> Int -> Int

...虽然,您仍然可以根据需要引入b变量。 您将需要一个方程式约束 (基本上是仅包含单个类型的临时类型类)

{-# LANGUAGE TypeFamilies #-}

sum_divide :: (Num a, b ~ Int) => [a] -> b -> b -> b

数学家会反对类型集合之间的几个差异级别 将我的“集合”概念读作“事物的集合”。

在更复杂的设置,实际上你可以混合使用约束和类型,但是这是先进的东西。

接受Num和2个int的列表并返回int的函数的签名为:

_sum_divide :: (Num a) => [a] -> Int -> Int -> Int

粗箭头之前的部分指定了约束。 它后面的部分是您使用约束的地方。

您有两个主要问题:

  • 签名中应该只有1个约束列表。

  • Int不是Typeclass。 (Num a)表示a可以是任何支持Num Typeclass的类型。 但是, Int是具体类型,而不是Typeclass,因此(Int b)没有意义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM