无法理解为什么我的类型的 MonoFoldable 无法编译,或者错误消息
Cannot understand why MonoFoldable for my type doesn't compile, or the error message
我有以下代码:
{-# LANGUAGE NoImplicitPrelude, OverloadedStrings, TypeFamilies #-}
module AI.Analysis.Rules where
import ClassyPrelude
-- Our set of rules
data RuleSet a = RuleSet [Rule a] [Rule a]
deriving (Eq)
mkRuleSet :: (Ord a) => [Rule a] -> RuleSet a
mkRuleSet rules = uncurry RuleSet (partition isStandard uniques)
where uniques = ordNub rules
isStandard x = case x of
Standard _ _ -> True
LastResort _ -> False
instance (Show a) => Show (RuleSet a) where
show (RuleSet s l) = unlines [toLines s, "----", toLines l]
where toLines = unlines . fmap show
instance (Ord a) => Monoid (RuleSet a) where
mempty = RuleSet [] []
mappend (RuleSet s1 l1) (RuleSet s2 l2) = RuleSet (ordNub (s1 ++ s2)) (ordNub (l1 ++ l2))
instance (Ord a) => Semigroup (RuleSet a) where
(<>) = mappend
type instance Element (RuleSet a) = (Rule a)
instance MonoFoldable (RuleSet a) --this is unhappy
-- A rule in our system
-- For now, we assume rules *individually* are always internally-consistent
data Rule a = Standard [a] a | LastResort a
deriving (Eq)
mkRule :: (Eq a, Ord a) => [a] -> a -> Rule a
mkRule as c = case as of
[] -> LastResort c
_ -> Standard ((sort . ordNub) as) c
-- Last-resort rules and standard rules cannot be compared for consistency
mutuallyConsistent :: (Eq a) => Rule a -> Rule a -> Maybe Bool
mutuallyConsistent (LastResort c1) (LastResort c2) = Just (c1 == c2)
mutuallyConsistent (Standard as1 c1) (Standard as2 c2) = Just ((as1 /= as2) || (c1 == c2))
mutuallyConsistent _ _ = Nothing
instance (Show a) => Show (Rule a) where
show x = case x of
Standard as c -> formatAnd as ++ " -> " ++ show c
LastResort c -> "-> " ++ show c
where formatAnd = unwords . intersperse "^" . map show . otoList
-- LastResort rules are always ordered smaller than standard ones
instance (Ord a) => Ord (Rule a) where
(<=) (LastResort _) (Standard _ _) = True
(<=) (Standard _ _) (LastResort _) = False
(<=) (LastResort c1) (LastResort c2) = c1 <= c2
(<=) (Standard as1 c1) (Standard as2 c2) = (as1 <= as2) || (c1 <= c2)
但是,我从编译器中收到以下错误,我无法理解其含义:
/home/koz/documents/uni/research/summer-research-2015/clinical/rules-analysis/src/AI/Analysis/Rules.hs:47:10:
Couldn't match type ‘a’ with ‘Rule a’
‘a’ is a rigid type variable bound by
the instance declaration
at /home/koz/documents/uni/research/summer-research-2015/clinical/rules-analysis/src/AI/Analysis/Rules.hs:47:10
Expected type: Element (RuleSet a)
Actual type: a
Relevant bindings include
ofoldMap :: (Element (RuleSet a) -> m) -> RuleSet a -> m
(bound at /home/koz/documents/uni/research/summer-research-2015/clinical/rules-analysis/src/AI/Analysis/Rules.hs:47:10)
In the expression:
mono-traversable-0.10.0.1:Data.MonoTraversable.$gdmofoldMap
In an equation for ‘ofoldMap’:
ofoldMap
= mono-traversable-0.10.0.1:Data.MonoTraversable.$gdmofoldMap
In the instance declaration for ‘MonoFoldable (RuleSet a)’
据我所知,我的想法似乎有道理 - 毕竟,RuleSet
只是 Rule
的容器,应该允许折叠,但错误消息问题对我来说没有任何意义。有人可以澄清我在这里没有掌握的内容吗?
您是否尝试过实际实施 class?默认定义和您的类型系列似乎有些奇怪。如果您至少定义了以下内容,那么文件类型将检查:
instance MonoFoldable (RuleSet a) where --this is unhappy
ofoldl1Ex' = undefined
ofoldr1Ex = undefined
ofoldl' = undefined
ofoldr = undefined
ofoldMap = undefined
编辑:classy 序曲,我现在知道我永远不会使用它,它具有默认实现和类型签名,其中包括约束 t a ~ mono, a ~ Element (t a)
。仔细工作,因为我不得不在这里三思而后行。 t a ~ RuleSet a0
所以 t == RuleSet
和 a == a0
。然后 a ~ Element (RuleSet a)
,这是您在消息中的确切错误,会建议 a ~ Rule a
,这是不对的。
澄清默认实现:因为有大量类型是适当多态的 - 因此 Functor
的实例 - MonoFunctor
提供了一种简单的方法来使它们也MonoFunctor
的实例,来自 default method signatures。如果您有 Functor
,只需声明 instance MonoFunctor
就足够了。
在您的情况下,您会收到一条令人困惑的错误消息,因为您的类型实际上是 Functor
,但与您想要的 MonoFunctor
实例类型不同。具体来说,根据其形状,RuleSet a
是 a
的 Functor
,而您希望它是 Rule a
。这没有什么错,它只是与默认实现冲突,因此您需要提供单独的实现。
请注意,这并非特定于您的类型:任何不是从 Functor
到 MonoFunctor
的简单转换的内容都需要这项工作。这适用于某些 built-in 实例,例如 Text
和 ByteString
.
我有以下代码:
{-# LANGUAGE NoImplicitPrelude, OverloadedStrings, TypeFamilies #-}
module AI.Analysis.Rules where
import ClassyPrelude
-- Our set of rules
data RuleSet a = RuleSet [Rule a] [Rule a]
deriving (Eq)
mkRuleSet :: (Ord a) => [Rule a] -> RuleSet a
mkRuleSet rules = uncurry RuleSet (partition isStandard uniques)
where uniques = ordNub rules
isStandard x = case x of
Standard _ _ -> True
LastResort _ -> False
instance (Show a) => Show (RuleSet a) where
show (RuleSet s l) = unlines [toLines s, "----", toLines l]
where toLines = unlines . fmap show
instance (Ord a) => Monoid (RuleSet a) where
mempty = RuleSet [] []
mappend (RuleSet s1 l1) (RuleSet s2 l2) = RuleSet (ordNub (s1 ++ s2)) (ordNub (l1 ++ l2))
instance (Ord a) => Semigroup (RuleSet a) where
(<>) = mappend
type instance Element (RuleSet a) = (Rule a)
instance MonoFoldable (RuleSet a) --this is unhappy
-- A rule in our system
-- For now, we assume rules *individually* are always internally-consistent
data Rule a = Standard [a] a | LastResort a
deriving (Eq)
mkRule :: (Eq a, Ord a) => [a] -> a -> Rule a
mkRule as c = case as of
[] -> LastResort c
_ -> Standard ((sort . ordNub) as) c
-- Last-resort rules and standard rules cannot be compared for consistency
mutuallyConsistent :: (Eq a) => Rule a -> Rule a -> Maybe Bool
mutuallyConsistent (LastResort c1) (LastResort c2) = Just (c1 == c2)
mutuallyConsistent (Standard as1 c1) (Standard as2 c2) = Just ((as1 /= as2) || (c1 == c2))
mutuallyConsistent _ _ = Nothing
instance (Show a) => Show (Rule a) where
show x = case x of
Standard as c -> formatAnd as ++ " -> " ++ show c
LastResort c -> "-> " ++ show c
where formatAnd = unwords . intersperse "^" . map show . otoList
-- LastResort rules are always ordered smaller than standard ones
instance (Ord a) => Ord (Rule a) where
(<=) (LastResort _) (Standard _ _) = True
(<=) (Standard _ _) (LastResort _) = False
(<=) (LastResort c1) (LastResort c2) = c1 <= c2
(<=) (Standard as1 c1) (Standard as2 c2) = (as1 <= as2) || (c1 <= c2)
但是,我从编译器中收到以下错误,我无法理解其含义:
/home/koz/documents/uni/research/summer-research-2015/clinical/rules-analysis/src/AI/Analysis/Rules.hs:47:10:
Couldn't match type ‘a’ with ‘Rule a’
‘a’ is a rigid type variable bound by
the instance declaration
at /home/koz/documents/uni/research/summer-research-2015/clinical/rules-analysis/src/AI/Analysis/Rules.hs:47:10
Expected type: Element (RuleSet a)
Actual type: a
Relevant bindings include
ofoldMap :: (Element (RuleSet a) -> m) -> RuleSet a -> m
(bound at /home/koz/documents/uni/research/summer-research-2015/clinical/rules-analysis/src/AI/Analysis/Rules.hs:47:10)
In the expression:
mono-traversable-0.10.0.1:Data.MonoTraversable.$gdmofoldMap
In an equation for ‘ofoldMap’:
ofoldMap
= mono-traversable-0.10.0.1:Data.MonoTraversable.$gdmofoldMap
In the instance declaration for ‘MonoFoldable (RuleSet a)’
据我所知,我的想法似乎有道理 - 毕竟,RuleSet
只是 Rule
的容器,应该允许折叠,但错误消息问题对我来说没有任何意义。有人可以澄清我在这里没有掌握的内容吗?
您是否尝试过实际实施 class?默认定义和您的类型系列似乎有些奇怪。如果您至少定义了以下内容,那么文件类型将检查:
instance MonoFoldable (RuleSet a) where --this is unhappy
ofoldl1Ex' = undefined
ofoldr1Ex = undefined
ofoldl' = undefined
ofoldr = undefined
ofoldMap = undefined
编辑:classy 序曲,我现在知道我永远不会使用它,它具有默认实现和类型签名,其中包括约束 t a ~ mono, a ~ Element (t a)
。仔细工作,因为我不得不在这里三思而后行。 t a ~ RuleSet a0
所以 t == RuleSet
和 a == a0
。然后 a ~ Element (RuleSet a)
,这是您在消息中的确切错误,会建议 a ~ Rule a
,这是不对的。
澄清默认实现:因为有大量类型是适当多态的 - 因此 Functor
的实例 - MonoFunctor
提供了一种简单的方法来使它们也MonoFunctor
的实例,来自 default method signatures。如果您有 Functor
,只需声明 instance MonoFunctor
就足够了。
在您的情况下,您会收到一条令人困惑的错误消息,因为您的类型实际上是 Functor
,但与您想要的 MonoFunctor
实例类型不同。具体来说,根据其形状,RuleSet a
是 a
的 Functor
,而您希望它是 Rule a
。这没有什么错,它只是与默认实现冲突,因此您需要提供单独的实现。
请注意,这并非特定于您的类型:任何不是从 Functor
到 MonoFunctor
的简单转换的内容都需要这项工作。这适用于某些 built-in 实例,例如 Text
和 ByteString
.