简体   繁体   English

顶级 OverloadedLists 文字

[英]Top-level OverloadedLists literal

I've got a test suite for a refactoring exercise where I'd like it to be compatible with both Data.List and Data.List.NonEmpty .我有一个用于重构练习的测试套件,我希望它与Data.ListData.List.NonEmpty兼容。 The exercise consists of a function foo :: [Foo] -> Foo and the test suite has some练习包含一个函数foo :: [Foo] -> Foo并且测试套件有一些

data Case = Case
  { description :: String
  , input :: [Foo]
  , expected :: Foo
  }

cases :: [Case]
cases =
  [ Case { description = "blah blah"
         , input = [Foo 1, Foo 2, Foo 3]
         , expected = Foo 1
         }
  , ...
  ]

To make the test suite polymorphic with OverloadedLists , I tried为了使用OverloadedLists使测试套件具有多态性,我尝试了

{-# LANGUAGE OverloadedLists #-}
...

data Case list = Case
  { description :: String
  , input :: list Foo
  , expected :: Foo
  }

cases =
  [ Case { description = "blah blah"
         , input = [Foo 1, Foo 2, Foo 3]
         , expected = Foo 1
         }
  , ...
  ]

but this gives me the error但这给了我错误

    • Couldn't match expected type ‘GHC.Exts.Item (list0 Foo)’
                  with actual type ‘Foo’
      The type variable ‘list0’ is ambiguous
      ...
   |
50 |          , input = [Foo 1, Foo 2, Foo 3]
   |                     ^^^^^

I thought to move the IsList list constraint to the Case data type, like so我想将IsList list约束移动到Case数据类型,就像这样

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedLists #-}
...

data Case list where
  Case :: IsList list => String -> list Foo -> Foo -> Case list

cases =
  [ Case "blah blah" [Foo 1, Foo 2, Foo 3] (Foo 1), ... ]

but this gives me the error但这给了我错误

    • Expected kind ‘* -> *’, but ‘list’ has kind ‘*’
    • In the type ‘list Foo’
      In the definition of data constructor ‘Case’
      In the data declaration for ‘Case’
   |        
24 |   Case :: IsList list => String -> list Foo -> Foo -> Case list
   |                                    ^^^^^^^^

I'm not sure what the simplest approach here is.我不确定这里最简单的方法是什么。 Any hints?任何提示?

The reason this does not work is because the Item type of a List (l Foo) => l is not per se Foo .这不起作用的原因是因为List (l Foo) => lItem类型本身不是Foo The extension makes abstraction of that, and thus it expects the elements of your list literal to be of type Item (l Foo) .该扩展对其进行了抽象,因此它期望您的列表文字的元素为Item (l Foo)类型。

You can however add a type constraint that says that the items are indeed of type Foo :但是,您可以添加一个类型约束,表明这些项目确实是Foo类型:

{-# LANGUAGE OverloadedLists #-}

data Case list = Case
  { description :: String
  , input :: list Foo
  , expected :: Foo
  }

cases :: (IsList (l Foo), Item (l Foo) ~ Foo) => [Case l]
cases = [
    Case { description = "blah blah"
         , input = [Foo 1, Foo 2, Foo 3]
         , expected = Foo 1
         }
  ]

Here we thus say that the Item (l Foo) should be the same as Foo .因此,我们在这里说Item (l Foo)应该与Foo相同。

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

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