Haskell类型声明

时间:2012-05-07 18:10:42

标签: haskell types

在Haskell中,为什么编译:

splice :: String -> String -> String
splice a b = a ++ b
main = print (splice "hi" "ya")

但这不是:

splice :: (String a) => a -> a -> a
splice a b = a ++ b
main = print (splice "hi" "ya")

>> Type constructor `String' used as a class

我原以为这些都是一样的。有没有办法使用第二种样式,避免重复类型名称3次?

5 个答案:

答案 0 :(得分:13)

类型中的=>语法适用于typeclasses

当您说f :: (Something a) => a时,您并不是说a Something,而是说它是“一组“Something类型。

例如,Num是一个类型类,包括IntFloat等类型。 但是,没有类型Num,所以我不能说

f :: Num -> Num
f x = x + 5

但是,我可以说

f :: Int -> Int
f x = x + 5

f :: (Num a) => a -> a
f x = x + 5

答案 1 :(得分:3)

实际上,有可能:

Prelude> :set -XTypeFamilies
Prelude> let splice :: (a~String) => a->a->a; splice a b = a++b
Prelude> :t splice
splice :: String -> String -> String

这使用等式约束~。但是我会避免这种情况,它不仅仅是简单地编写String -> String -> String,而是更难以理解,并且编译器难以解决。

答案 2 :(得分:3)

  

有没有办法使用第二种样式,避免重复类型名称3次?

为简化类型签名,您可以使用类型同义词。例如,你可以写

type S = String
splice :: S -> S -> S

或类似

type BinOp a = a -> a -> a
splice :: BinOp String

然而,对于像String -> String -> String这样简单的事情,我建议只输入它。类型同义词应该用于使类型签名更具可读性,而不是更少。

在这种特殊情况下,您还可以将类型签名概括为

splice :: [a] -> [a] -> [a]

因为它根本不依赖于元素。

答案 3 :(得分:1)

嗯...... String是一种类型,你试图将它用作一个类。

如果您想要splice函数的多态版本示例,请尝试:

import Data.Monoid

splice :: Monoid a=> a -> a -> a
splice = mappend

编辑:所以这里的语法是=>左边出现的大写字是类型类约束变量显示在{{1}的右侧}。右边的所有大写单词都是 types

的名称

答案 4 :(得分:1)

您可以在this Learn You a Haskell章节中找到解释。