简体   繁体   English

在Haskell中为复合类型定义实例

[英]Defining an instance for a composite type in Haskell

I have a type that has a mappend -like function but not a real mappend , so it is not a Semigroup . 我有一个类似mappend的函数,但不是真正的mappend ,所以它不是Semigroup For instance: 例如:

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

I always deal with MyType when it is wrapped in Maybe . 当它包含在Maybe时,我总是处理MyType I need semantics that would be perfectly represented if I could define a Semigroup instance on the "combined" type Maybe MyType like this: 如果我可以在“组合”类型上定义一个Semigroup实例,那么我需要能够完美表示的语义。 Maybe MyType如下:

instance Semigroup (Maybe MyType) where
  (Just x) <> (Just y) = myMerge x y
  Nothing  <> Nothing  = Nothing
  Nothing  <> (Just _) = Nothing
  (Just _) <> Nothing  = Nothing

Ie when both parameters are Just 's, I can get either a Just or Nothing , otherwise I always get Nothing . 即当两个参数都是Just ,我可以得到JustNothing ,否则我总是得到Nothing But this is not possible, I get an error: 但这是不可能的,我收到一个错误:

All instance types must be of the form (T a1 ... an)

How can I represent the semantics that I need? 我如何表示我需要的语义?

The instance you defined is illegal because it is basically trying to define a different (partial) Semigroup instance for Maybe, but Maybe already has one. 您定义的实例是非法的,因为它基本上是尝试为Maybe定义一个不同的(部分)Semigroup实例,但是Maybe已经有了一个。 Instead, use a newtype wrapper: 相反,使用newtype包装器:

newtype MaybeMyType = MaybeMyType (Maybe MyType)

instance Semigroup MaybeMyType where
  ...

You will have to interact with your type through this MaybeMyType wrapper in the cases where you want to use its Semigroup instance. 在您想要使用其Semigroup实例的情况下,您必须通过此MaybeMyType包装器与您的类型进行交互。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM