为什么我不能这样定义[Applicative Int]
:
Prelude Control.Applicative> let xs = [pure 5, pure 5] :: [Applicative Int]
我收到以下编译时错误,由于这个answer,我理解这一点。
<interactive>:60:43:
Kind mis-match
The first argument of `Applicative' should have kind `* -> *',
but `Int' has kind `*'
In an expression type signature: [Applicative Int]
In the expression: [pure 5, pure 5] :: [Applicative Int]
In an equation for `xs': xs = [pure 5, pure 5] :: [Applicative Int]
但是,我不确定如何解决此错误。
答案 0 :(得分:9)
Applicative
是类型类,而不是类型。您可以拥有类型的值,该类型甚至可以是类型类的实例,但值必须与类型相关联,并且您说您希望值具有类型类而不是类型。
某些类型是Applicative
的实例
Maybe
[]
IO
如果您尝试使用这些类型运行它,它应该可以工作:
ghci> [pure 5, pure 5] :: [Maybe Int]
[Just 5, Just 5]
ghci> [pure 5, pure 5] :: [[Int]]
[[5], [5]]
ghci> sequence ([pure 5, pure 5] :: [IO Int])
[5, 5]
答案 1 :(得分:5)
Applicative Int
是一个(荒谬的,但暂时忽略它)约束。约束不是类型。约束永远不会出现在普通的Haskell类型中,只能出现在类型签名的 constraints 中。通常,你有像
anyEqual :: Eq a => a -> a -> a -> Bool
anyEqual a b c = a==b || a==c || b==c
或者,或许更有洞察力,
5 :: Num a => a
5 = 4 + 1
请注意,只有在包含类型变量(a
此处)时,约束基本上才有意义。正是这些约束将a
限制为类型类Num
。
了解类型类与OO语言中的抽象类不同,这一点非常重要。它不是,&#34; Eq
可以是它自己的类型,Eq T
表示编译器知道如何解释T
对象作为Eq
对象&#34;。
相反,它是这样的:Eq
指定一组方法(为简单起见,说它只是(==) :: a -> a -> Bool
)。然后将这些方法作为Eq
- 限制多态函数的额外参数给出:字典。内部实现类似于
anyEqualBy :: (a->a->Bool) -> a->a->a->Bool
anyEqualBy eqFunc a b c = eqFunc a b || eqFunc a c || eqFunc b c
这解释了一些事情:
Applicative Int
并不是很有用。原因是,在其中没有可能需要字典的类型变量:如果Int
在应用类中是,那么这些方法可以简单地全部内联。拥有&#34;约束列表&#34;的类型是没有意义的。让我们看看这样的东西需要转化为......
anyEqualCrazy :: [Eq a] => a->a->a->Bool
anyEqualCrazyBy :: [a->a->Bool] -> a->a->a->Bool
所以这将收到一整个词典列表。这与函数处理某些类型的列表完全不同。