在 Haskell 中定义复合类型的实例
Defining an instance for a composite type in Haskell
我有一个类型具有类似 mappend
的功能,但不是真正的 mappend
,因此它不是 Semigroup
。例如:
data MyType = MyType Int deriving Show
myMerge :: MyType -> MyType -> Maybe MyType
myMerge (MyType x) (MyType y)
| (x < 0) || (y < 0) = Nothing
| otherwise = Just $ MyType $ x + y
我总是处理 MyType
包裹在 Maybe
中的情况。如果我可以像这样在 "combined" 类型 Maybe MyType
上定义 Semigroup
实例,我需要能够完美表示的语义:
instance Semigroup (Maybe MyType) where
(Just x) <> (Just y) = myMerge x y
Nothing <> Nothing = Nothing
Nothing <> (Just _) = Nothing
(Just _) <> Nothing = Nothing
即当两个参数都是 Just
时,我可以得到 Just
或 Nothing
,否则我总是得到 Nothing
。但这是不可能的,我得到一个错误:
All instance types must be of the form (T a1 ... an)
如何表示我需要的语义?
您定义的实例是非法的,因为它基本上是在尝试为 Maybe 定义一个不同的(部分)Semigroup 实例,但 Maybe 已经有一个。相反,使用新类型包装器:
newtype MaybeMyType = MaybeMyType (Maybe MyType)
instance Semigroup MaybeMyType where
...
如果您想使用其 Semigroup 实例,则必须通过此 MaybeMyType 包装器与您的类型进行交互。
我有一个类型具有类似 mappend
的功能,但不是真正的 mappend
,因此它不是 Semigroup
。例如:
data MyType = MyType Int deriving Show
myMerge :: MyType -> MyType -> Maybe MyType
myMerge (MyType x) (MyType y)
| (x < 0) || (y < 0) = Nothing
| otherwise = Just $ MyType $ x + y
我总是处理 MyType
包裹在 Maybe
中的情况。如果我可以像这样在 "combined" 类型 Maybe MyType
上定义 Semigroup
实例,我需要能够完美表示的语义:
instance Semigroup (Maybe MyType) where
(Just x) <> (Just y) = myMerge x y
Nothing <> Nothing = Nothing
Nothing <> (Just _) = Nothing
(Just _) <> Nothing = Nothing
即当两个参数都是 Just
时,我可以得到 Just
或 Nothing
,否则我总是得到 Nothing
。但这是不可能的,我得到一个错误:
All instance types must be of the form (T a1 ... an)
如何表示我需要的语义?
您定义的实例是非法的,因为它基本上是在尝试为 Maybe 定义一个不同的(部分)Semigroup 实例,但 Maybe 已经有一个。相反,使用新类型包装器:
newtype MaybeMyType = MaybeMyType (Maybe MyType)
instance Semigroup MaybeMyType where
...
如果您想使用其 Semigroup 实例,则必须通过此 MaybeMyType 包装器与您的类型进行交互。