创建[Applicative Int]

时间:2014-07-28 00:52:19

标签: haskell

为什么我不能这样定义[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]

但是,我不确定如何解决此错误。

2 个答案:

答案 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
    

    所以这将收到一整个词典列表。这与函数处理某些类型的列表完全不同。