正如问题所述,我在定义具有不同类型参数的函数时遇到了一些麻烦。 (Num数组,两个参数Int和返回Int)。
这是功能标题:
apply(Time_df,2,strftime, format="%H:%M:%S")
Time1 Time2 Time3 Time4 Time5
[1,] "07:00:00" "19:00:00" "00:00:00" "00:00:00" "00:00:00"
[2,] "00:00:00" "00:00:00" "00:00:00" "00:00:00" "00:00:00"
[3,] "00:00:00" "00:00:00" "00:00:00" "00:00:00" "00:00:00"
[4,] "06:00:00" "22:00:00" "00:00:00" "00:00:00" "00:00:00"
[5,] "08:00:00" "21:00:00" "00:00:00" "00:00:00" "00:00:00"
我得到这个错误,我无法弄清楚
_sum_divide :: (Num a) => [a] -> (Int b) => b -> b -> b
抱歉这个愚蠢的错误,我是Haskell的菜鸟。
谢谢,祝你有个美好的一天/晚上。
答案 0 :(得分:2)
这似乎是类型和类型的概念之间的基本混淆。 OO语言将所有这些组合在一起,但在Haskell中它们是根本不同的东西。
类型是设置†的值。例如,类型Bool
包含值False
和True
。类型Int
包含值0
,1
... 9223372036854775807
及其否定值。
类型类是一组类型。例如,类Num
包含类型Int
,类型Double
,类型Rational
...以及您自己的T
类型,如果您只需定义instance Num T
。
通常,只需命名它们,就可以在函数签名中使用 types 。例如,
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
),你要写
sum_divide :: (Num a, Integral b) => [a] -> b -> b -> b
或者,如果你的意思是Int
- 那只是一种类型,没有理由为它引入类型变量。
sum_divide :: Num a => [a] -> Int -> Int -> Int
...尽管如此,如果您愿意, 仍可以引入b
变量。您需要一个等式约束(那些基本上只是一种类型的ad-hoc类型)
{-# LANGUAGE TypeFamilies #-}
sum_divide :: (Num a, b ~ Int) => [a] -> b -> b -> b
† 数学家会反对类型,集和类之间的几个级别的差异。把我的“集合”概念看作“事物的集合”。
‡ 在更复杂的设置中,您实际上可以混合约束和类型,但这是高级内容。
答案 1 :(得分:1)
获取Num
和2 int列表并返回int的函数的签名是:
_sum_divide :: (Num a) => [a] -> Int -> Int -> Int
粗箭头前面的部分指定了约束。之后的部分是您使用约束的地方。
您有两个主要问题:
签名中只应有1个约束列表。
Int
不是类型类。 (Num a)
表示a
可以是支持Num
类型类的任何类型。 Int
是一个具体的类型,而不是类型类,所以(Int b)
没有意义。