【发布时间】:2017-12-15 03:15:47
【问题描述】:
我有以下 Haskell 代码:
type family Element t
class ToList t where
toList :: t -> [Element t]
之前有人建议我将 Element 设为关联类型族:Foldable IntSet
我尝试实施这种方法。但这不适用于我的情况。这是整个代码:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
import Prelude hiding (toList)
import qualified Data.Foldable as Foldable (toList)
import Data.Text (Text, unpack)
class ToList t where
type Element t :: *
toList :: t -> [Element t]
-- | This instance makes 'ToList' compatible and overlappable by 'Foldable'.
instance {-# OVERLAPPABLE #-} Foldable f => ToList (f a) where
type Element (f a) = a
toList = Foldable.toList
instance ToList Text where
type Element Text = Char
toList = unpack
newtype WrappedList l = WrappedList l
instance ToList l => ToList (WrappedList l) where
type Element (WrappedList l) = Element l
toList (WrappedList l) = toList l
当我使用 GHC-8.2.2 编译此代码时,我看到以下错误:
Element.hs:14:10: error:
Conflicting family instance declarations:
Element (f a) = a -- Defined at Element.hs:14:10
Element (WrappedList l) = Element l -- Defined at Element.hs:24:10
|
14 | type Element (f a) = a
| ^^^^^^^^^^^^^^^^^
我该如何解决这个错误?我不知道如何使它与关联的类型族兼容...
【问题讨论】:
-
你不能 - 开放类型族不允许重叠。您可以使用多参数类型类。但是,我看不到
WrappedList实例的用途。 -
@user240738 我猜这是一个简单的健全性检查,以确保稍微复杂的类型既可以是实例也可以是简单的。
-
@user2407038 另一个让我满意的解决方案是拥有
type Element类型族的默认实现,并且能够覆盖这个实现。 @HTNW 关于健全性检查的观点是正确的 :) 但在我的情况下,我有class ToList t => Container t其中Container有大约 15 种方法。而这个WrappedList包装器通过Container实例为[a]实现了所有Container方法。如果您想使用Container方法但又不想为您的数据类型实现约 15 种方法,这可能会很有用。 -
@user2407038 对这个问题的回答建议使用_默认关联单射类型family_,但我不知道如何使用它:stackoverflow.com/questions/46206079/…
标签: haskell type-families