【问题标题】:Lists of data types: "could not deduce (a ~ SomeType) from the context (SomeTypeclass a)"数据类型列表:“无法从上下文 (SomeTypeclass a) 推导出 (a ~ SomeType)”
【发布时间】:2019-02-25 03:57:21
【问题描述】:

Haskell 的类型系统存在以下问题:我试图声明一个数据类型并从函数返回一个包含该类型元素的列表。不幸的是,即使是最小的测试用例,例如

data SampleType = SampleTypeConstructor

instance Show SampleType where
    show x = "(SampleType)"

stList :: (Show a) => [a]
stList = [(SampleTypeConstructor)]

main = do {
    putStrLn (show stList)
}

失败,来自 ghc-7.0.2 和 ghc-7.1.20110327 的错误消息如下:

tcase.hs:7:12:
    Could not deduce (a ~ SampleType)
    from the context (Show a)
      bound by the type signature for stList :: Show a => [a]
      at tcase.hs:7:1-34
      `a' is a rigid type variable bound by
          the type signature for stList :: Show a => [a] at tcase.hs:7:1
    In the expression: (SampleTypeConstructor)
    In the expression: [(SampleTypeConstructor)]
    In an equation for `stList': stList = [(SampleTypeConstructor)]

【问题讨论】:

    标签: haskell types


    【解决方案1】:

    违规行是stList :: (Show a) => [a]。您声明 stList 是一个多态列表,其中包含满足显示约束的任何元素。但是 stList 不是多态列表!这是SampleTypes 的列表。所以删除签名并查看 ghci 推断什么,或者只是给它正确的签名::: [SampleType]

    【讨论】:

      【解决方案2】:
      stList :: (Show a) => [a]
      

      是说给定 any Show 实例为 any 类型 a,您将返回该类型的元素列表。

      stList = [SampleTypeConstructor]
      

      返回SampleTypes 的列表,虽然这是一个存在Show 实例的元素列表,但它并不是一个适用于a 的每个选择的列表。

      实际上,对于这种不涉及底部的类型,您可能找到的唯一居民是[],因为Show a 没有提供任何构造a 的机制。

      要解决此问题,您可以根据您的最终目标做一些事情之一。

      您可能只想让stList 具有更窄的类型:

      stList :: [SampleType]
      

      您可能想要构建某种类型,例如

      newtype Showable = Showable (Int -> String -> String)
      

      它明确地捕获了 Show 实例的相关部分。 (您也可以使用存在类型执行此操作,但此版本是 Haskell 98。)

      instance Show Showable where
          showsPrec d (Showable f) = f d
      
      showable :: Show a => a -> Showable
      showable a = Showable (\d -> showsPrec d a)
      

      然后你可以制作一个 Showables 列表。

      stList :: [Showable]
      stList = [showable SampleTypeConstructor]
      

      但最终这取决于您要完成的工作。

      【讨论】:

      • 好吧,我想完成一些多态性(列表包含所有遵守类型类的任何元素),但只有在睡了几个小时后,我才意识到 Haskell 提供的默认列表不是t 多态。哎呀,对不起。
      【解决方案3】:

      Haskell 确实支持元素的异构列表,只要它们的元素被正确包装(参见repl.it 上的实时代码):

      {-# LANGUAGE GADTs #-}
      
      -- your sample type
      data SampleType = SampleConstructor
      
      instance Show SampleType where
        show _ = "(SampleType)"
      
      -- MkShowable wrapper
      data Showable where
        MkShowable :: Show a => a -> Showable
      
      instance Show Showable where
        show (MkShowable a) = show a
      
      
      main = do
        let myList :: [Showable]
            myList = [MkShowable SampleConstructor, MkShowable 1, MkShowable True]
        putStrLn $ show myList
        -- ["(SampleType)","1","True"]
      

      更多选项请参见Heterogenous collections

      【讨论】:

        猜你喜欢
        • 2023-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-15
        • 2018-04-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多