Lists of data types: “could not deduce (a ~ SomeType) from the context (SomeTypeclass a)”

后端 未结 3 420
闹比i
闹比i 2021-01-03 22:52

I have the following problem with Haskell\'s type system: I am trying to declare a data type and return a list containing elements of this type from a function. Unfortunatel

相关标签:
3条回答
  • 2021-01-03 23:18

    the offending line is stList :: (Show a) => [a]. You're declaring that stList is a polymorphic list that holds any element which satisfies the show constraint. But stList isn't a polymorphic list! It's a list of SampleTypes. So remove the signature and see what ghci infers, or just give it the correct signature: :: [SampleType].

    0 讨论(0)
  • 2021-01-03 23:31

    Haskell does support heterogenous lists of elements, provided their elements are correctly wrapped (see live code on 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"]
    

    See Heterogenous collections for more options.

    0 讨论(0)
  • 2021-01-03 23:37
    stList :: (Show a) => [a]
    

    is saying that given any Show instance for any type a, you are going return a list of elements of that type.

    stList = [SampleTypeConstructor]
    

    is returning list of SampleTypes, while that is a list of elements for which there exists a Show instance, it is not a list that works for every choice of a.

    In reality the only inhabitant you are likely to find for this type that doesn't involve bottoms is [], because Show a doesn't provide any mechanism to construct an a.

    To fix this you can do one of a few things, depending on your end goal.

    You may just want to let stList have the more narrow type:

    stList :: [SampleType]
    

    You may want to build some kind of type like

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

    which explicitly captures the relevant portion of the Show instance. (You can also do this with an existential type, but this version is Haskell 98.)

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

    Then you could make a list of Showables.

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

    But ultimately it depends on what you are trying to accomplish.

    0 讨论(0)
提交回复
热议问题