“是否有规范的haskell类型?”;一个或两个;?

“是否有规范的haskell类型?”;一个或两个;?,haskell,Haskell,我发现自己需要一个数据结构,它可能包含一个a,也可能包含一个B,而且肯定是其中之一。如果我要为这个东西建立一个通用的数据类型,它可能看起来像: data OneOrBoth a b = A a | B b | AB a b maybeA :: OneOrBoth a b -> Maybe a maybeB :: OneOrBoth a b -> Maybe b eitherL :: OneOrBoth a b -> Either a b -- Prefers a either

我发现自己需要一个数据结构,它可能包含一个
a
,也可能包含一个
B
,而且肯定是其中之一。如果我要为这个东西建立一个通用的数据类型,它可能看起来像:

data OneOrBoth a b = A a | B b | AB a b

maybeA :: OneOrBoth a b -> Maybe a
maybeB :: OneOrBoth a b -> Maybe b
eitherL :: OneOrBoth a b -> Either a b -- Prefers a
eitherR :: OneOrBoth a b -> Either a b -- Prefers b
hasBoth, hasExactlyOne, hasA, hasB :: OneOrBoth a b -> Bool
此数据结构是否有名称?在Haskell中是否有处理一个或两个结构的规范方法?

这对于表示两个值的组合非常有用,其中 如果两个输入中的任何一个为空,则定义组合。代数上,类型
这些AB
表示(A+B+AB),不容易将其考虑在内 总和和乘积-像
这样的类型a(B,可能是a)
不清楚且 使用不便


数据。这些都提到过,可能是最好的选择,但如果我要推出自己的,我会这样做:

import Control.Applicative ((<$>), (<*>))

type These a b = Either (Either a b) (a, b)

maybeA :: These a b -> Maybe a
maybeA (Left (Left a)) = Just a
maybeA (Right (a, _))  = Just a
maybeA _               = Nothing

maybeB :: These a b -> Maybe b
maybeB (Left (Right b)) = Just b
maybeB (Right (_, b))   = Just b
maybeB _                = Nothing

eitherA :: These a b -> Either a b
eitherA (Left (Left a))  = Left a
eitherA (Right (a, _))   = Left a
eitherA (Left (Right b)) = Right b

eitherB :: These a b -> Either a b
eitherB (Left (Right b)) = Right b
eitherB (Right (_, b))   = Right b
eitherB (Left (Left a))  = Left a

hasBoth, hasJustA, hasJustB, hasA, hasB :: These a b -> Bool

hasBoth (Right _) = True
hasBoth _         = False

hasJustA (Left (Left _)) = True
hasJustA _               = False

hasJustB (Left (Right _)) = True
hasJustB _                = False

hasA = (||) <$> hasBoth <*> hasJustA
hasB = (||) <$> hasBoth <*> hasJustB
import-Control.Applicative((),())
键入这些a b=或(或a b)(a,b)
这些a b->可能a
maybeA(左a))=只是一个
只是一个
也许什么都没有
也许b::这些a b->也许b
maybeB(左(右b))=只有b
maybeB(右(u,b))=只有b
可能没有
eitherA::这些a b->或a b
eitherA(左(左a))=左a
eitherA(右(a,)))=左a
eitherA(左(右b))=右b
eitherB::这些a b->a b
eitherB(左(右b))=右b
(右(u,b))=右b
eitherB(左(左a))=左a
hasab,hasJustA,hasjustab,hasA,hasB::这些a b->Bool
HasAll(右)=真
hasseath=假
hasJustA(左(左))=真
hasJustA=错误
hasJustB(左(右))=真
hasJustB=错误
hasA=(| |)hasA和hasJustA
hasB=(| |)hasB和hasJustB
如果你想要“零、一或二者”,你就需要
1+A+B+A*B=(1+A)*(1+B)
(可能是A,可能是B)

您可以通过将
(可能是A,可能是B)
包装在
newtype
中并使用智能构造函数删除
(无,无)
来执行
A+B+A*B=(1+A)*(1+B)-1


为什么要停在两种类型上?三,四…?:-)如果你想要“零、一或两者”,你应该有
1+A+B+A*B=(1+A)*(1+B)
(可能是A,可能是B)
。这不是真正的规范,但肯定是比自己滚动更好的选择,虽然这个软件包有很多依赖项和附加项,可能对OPI有用,也可能不有用,但我不确定这是否真的比在所有情况下都使用自己的软件包要好。这听起来像是OP经常使用它,但如果这是一件小事,我不想引入对profunctors、mtl、半群等的依赖,因为谈论以文章命名的专有名词是多么困难,我写了一篇文章,它的明确优势是只引入
strict
bifunctors
。请不要用它,正是我要找的那种东西。谢谢虽然代数因子分解方法很好,但我不认为这实际上比简单地滚动自己的求和类型有任何优势。使用
newtype
基本上是同构的,现在模式匹配已经消失了。
module Some (
  Some(),
  this, that, those, some,
  oror, orro, roro, roor,
  swap
) where

import Control.Applicative ((<|>))

newtype Some a b = Some (Maybe a, Maybe b) deriving (Show, Eq)

-- smart constructors
this :: a -> Some a b
this a = Some (Just a,Nothing)

that :: b -> Some a b
that b = Some (Nothing, Just b)

those :: a -> b -> Some a b
those a b = Some (Just a, Just b)

-- catamorphism/smart deconstructor
some :: (a -> r) -> (b -> r) -> (a -> b -> r) -> Some a b -> r
some f _ _ (Some (Just a, Nothing)) = f a
some _ g _ (Some (Nothing, Just b)) = g b
some _ _ h (Some (Just a, Just b))  = h a b
some _ _ _ _ = error "this case should be unreachable due to smart constructors"

swap :: Some a b -> Some b a
swap ~(Some ~(ma,mb)) = Some (mb,ma)

-- combining operators
oror, orro, roro, roor :: Some a b -> Some a b -> Some a b

-- prefer the leftmost A and the leftmost B
oror (Some (ma,mb)) (Some (ma',mb')) = Some (ma <|> ma', mb <|> mb')
-- prefer the leftmost A and the rightmost B
orro (Some (ma,mb)) (Some (ma',mb')) = Some (ma <|> ma', mb' <|> mb)
-- prefer the rightmost A and the rightmost B
roro = flip oror
-- prefer the rightmost A and the leftmost B
roor = flip orro
λ this "red" `oror` that "blue" `oror` those "beige" "yellow"
Some (Just "red",Just "blue")
λ this "red" `orro` that "blue" `orro` those "beige" "yellow"
Some (Just "red",Just "yellow")
λ this "red" `roor` that "blue" `roor` those "beige" "yellow"
Some (Just "beige",Just "blue")
λ this "red" `roro` that "blue" `roro` those "beige" "yellow"
Some (Just "beige",Just "yellow")