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

时间:2017-03-27 18:43:11

标签: function haskell

正如问题所述,我在定义具有不同类型参数的函数时遇到了一些麻烦。 (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的菜鸟。

谢谢,祝你有个美好的一天/晚上。

2 个答案:

答案 0 :(得分:2)

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

  • 类型是设置的值。例如,类型Bool包含值FalseTrue。类型Int包含值01 ... 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,但约束是多余的,因为我们知道 IntNum个实例,编译器并没有忘记这一点。

多态函数中,约束非常有用。例如,以下函数使数字列表中的每个条目增至三倍,而并不关心数字具有哪种特定类型

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

类型变量的表示法a实际上是

的缩写
foo :: ∀ n . Num n => [n] -> [n]

意思是,对于所有数字类型n ,函数foon - 值列表映射到n - 值列表。

重要的是,约束与签名中的实际类型规范完全分开。例如,要为多态函数[a] -> b -> b -> b指定a应该是Num实例,bIntegral实例(整数类型的类) ,包含其他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)没有意义。