简体   繁体   English

本机的Haskell列表是否具有“真实”类型名称? 还是……我在这里做错了什么?

[英]Do native Haskell lists have a “real” type name? Or… what am I doing wrong here?

Following the article about Haskell type families , I found the courage to try it myself. 跟随有关Haskell类型族的文章之后,我发现了自己尝试这一点的勇气。 Well knowing that Lists are already Applicative and whatnot, just to see if I got the ideas right, I tried to do the following: 知道列表已经是可应用的,什么都没有,只是为了看看我是否正确,我尝试执行以下操作:

{-# LANGUAGE TypeFamilies #-}

class Iterable c where
    data Iterator c :: * -> *
    current :: Iterator c a -> Maybe a
    next :: Iterator c a -> Maybe (Iterator c a)

instance Iterable [] where
    data Iterator [] a = ListIterator [a] -- Problem in this line!
    current (ListIterator []) = Nothing
    current (ListIterator (x:xs)) = Just x
    next (ListIterator []) = Nothing
    next (ListIterator (x:xs)) = Just (ListIterator xs)

This is in analogy of the example code given in the above haskell tutorial. 这类似于上述haskell教程中给出的示例代码。 What this is supposed to do is, to implement the type family Iterable for native Haskell lists, generically. 这应该做的是一般地为本地Haskell列表实现类型为Iterable的系列。

I tried alternatively to write data Iterator [a] = ListIterator [a] but this yields the same error message as the code I show here: 我也尝试编写data Iterator [a] = ListIterator [a]但这会产生与我在此处显示的代码相同的错误消息:

 temp.hs:8:19: error:
    * Expecting one more argument to `[]'
      Expected a type, but `[]' has kind `* -> *'
    * In the first argument of `Iterable', namely `[]'
      In the instance declaration for `Iterable []'

Hence, my question, if I have an option to use the real type name for lists instead of [] , as I suspect, this is where my (syntactical?) problem is coming from. 因此,我的问题是,如果我可以选择对列表使用实型名称而不是[] ,我怀疑这就是我的(语法上的)问题的出处。

Note that the class does not really use its argument in any way at all, it only uses Iterator c but not c itself. 请注意,该类实际上根本没有以任何方式使用其参数,它仅使用Iterator c ,而不使用c本身。 That's ok in principle – c works basically just as a tag, to select some other type – though you should ask yourself whether that's really what you want and if a more direct approach wouldn't be better. 原则上没关系– c基本上像标签一样工作,以选择其他类型–尽管您应该问自己,这是否真的是您想要的,以及更直接的方法是否会更好。

The only real problem: because c isn't used by itself, the compiler has no way of knowing what kind this should have. 唯一真正的问题:由于c自身未使用,因此编译器无法知道c应该具有哪种类型 Ie, basically your class is polymorphically kinded , which Haskell98 doesn't allow... hence it defaults to the simplest possible kind, namely * . 即,基本上,您的类是多态的 ,Haskell98不允许这样做...因此它默认为最简单的类型,即* GHCi can tell you this: GHCi可以告诉您以下内容:

*Main> :k Iterable
Iterable :: * -> Constraint

So that would work for eg instance Iterable Int , because Int has kind * . 这样就可以用于例如instance Iterable Int ,因为Int具有* But [] doesn't, it has kind * -> * . 但是[]没有,它具有种类* -> * Hence that error message. 因此,该错误消息。

You can enable GHC's PolyKinds extension to avoid this defaulting: 您可以启用GHC的PolyKinds扩展来避免此默认设置:

{-# LANGUAGE PolyKinds     #-}

class Iterable c where
    data Iterator c :: * -> *
    current :: Iterator c a -> Maybe a
    next :: Iterator c a -> Maybe (Iterator c a)

Now it is 现在它是

*Main> :k Iterable
Iterable :: k -> Constraint

and therefore both instance Iterable Int will work (with k ~ * ) and instance Iterable [] too (with k ~ (* -> *) ). 因此, instance Iterable Int (也可以使用instance Iterable [] k ~ * )和instance Iterable [] (也可以使用k ~ (* -> *) )都可以使用。

Alternatively, you could manually state that c should always have kind * -> * : 另外,您可以手动声明c应该始终为kind * -> *

{-# LANGUAGE KindSignatures #-}

class Iterable (c :: * -> *) where
    data Iterator c :: * -> *
    current :: Iterator c a -> Maybe a
    next :: Iterator c a -> Maybe (Iterator c a)

Now instance Iterable [] would work, but instance Iterable Int wouldn't. 现在, instance Iterable []将起作用,但instance Iterable Int将不起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM