[英]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
包含值False
和True
。 类型Int
包含值0
, 1
... 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
,但是约束是多余的,因为我们知道 Int
是Num
实例,编译器并不会忘记这一点。
约束真正有用的地方是多态函数。 例如,以下函数将数字列表中的每个条目增加三倍,而不管数字具有哪种特定类型 :
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.