Skip to content

Commit cc140c3

Browse files
committed
Decidable-inspired interface for UnionInputType
1 parent 17fd6c3 commit cc140c3

File tree

1 file changed

+39
-36
lines changed

1 file changed

+39
-36
lines changed

dhall/src/Dhall.hs

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ module Dhall
7878
, inputConstructorWith
7979
, inputConstructor
8080
, inputUnion
81+
, (>|<)
8182

8283
-- * Miscellaneous
8384
, rawInput
@@ -1547,26 +1548,27 @@ inputRecord (RecordInputType inputTypeRecord) = InputType makeRecordLit recordTy
15471548
15481549
> injectStatus :: InputType Status
15491550
> injectStatus =
1550-
> inputUnion
1551-
> ( inputConstructorWith "Queued" inject (\case Queued n -> Just n; _ -> Nothing)
1552-
> <> inputConstructorWith "Result" inject (\case Result t -> Just t; _ -> Nothing)
1553-
> <> inputConstructorWith "Errored" inject (\case Errored e -> Just e; _ -> Nothing)
1554-
> )
1551+
> adapt
1552+
> >$< inputConstructorWith "Queued" inject
1553+
> >|< inputConstructorWith "Result" inject
1554+
> >|< inputConstructorWith "Errored" inject
1555+
> where
1556+
> adapt (Queued n) = Left (Left n)
1557+
> adapt (Result t) = Left (Right t)
1558+
> adapt (Errored e) = Right e
15551559
15561560
Or, since we are simply using the `Inject` instance to inject each branch, we could write
15571561
15581562
> injectStatus :: InputType Status
15591563
> injectStatus =
1560-
> inputUnion
1561-
> ( inputConstructor "Queued" (\case Queued n -> Just n; _ -> Nothing)
1562-
> <> inputConstructor "Result" (\case Result t -> Just t; _ -> Nothing)
1563-
> <> inputConstructor "Errored" (\case Errored e -> Just e; _ -> Nothing)
1564-
> )
1565-
1566-
Note that the resulting 'InputType' is __not total__ unless we
1567-
appropriately aggregate each possibility. If we forgot to handle
1568-
a branch, the 'InputType' will throw a runtime exception when used on
1569-
an unhandled branch.
1564+
> adapt
1565+
> >$< inputConstructor "Queued"
1566+
> >|< inputConstructor "Result"
1567+
> >|< inputConstructor "Errored"
1568+
> where
1569+
> adapt (Queued n) = Left (Left n)
1570+
> adapt (Result t) = Left (Right t)
1571+
> adapt (Errored e) = Right e
15701572
-}
15711573
newtype UnionInputType a =
15721574
UnionInputType
@@ -1577,53 +1579,54 @@ newtype UnionInputType a =
15771579
( Expr Src X )
15781580
)
15791581
)
1580-
( Op (Data.Monoid.First (Expr Src X)) )
1582+
( Op (Expr Src X) )
15811583
a
15821584
)
15831585
deriving (Contravariant)
15841586

1585-
-- As of base 4.12, we can use :*: to derive this instance automatically
1586-
instance Semigroup (UnionInputType a) where
1587-
UnionInputType (Data.Functor.Product.Pair mx fx)
1588-
<> UnionInputType (Data.Functor.Product.Pair my fy)
1589-
= UnionInputType (Data.Functor.Product.Pair (mx <> my) (fx <> fy))
1587+
-- | Combines two 'UnionInputType' values. See 'UnionInputType' for usage
1588+
-- notes.
1589+
--
1590+
-- Ideally, this matches 'Data.Functor.Contravariant.Divisible.chosen';
1591+
-- however, this allows 'UnionInputType' to not need a 'Divisible' instance
1592+
-- itself (since no instance is possible).
1593+
(>|<) :: UnionInputType a -> UnionInputType b -> UnionInputType (Either a b)
1594+
UnionInputType (Data.Functor.Product.Pair (Control.Applicative.Const mx) (Op fx))
1595+
>|< UnionInputType (Data.Functor.Product.Pair (Control.Applicative.Const my) (Op fy)) =
1596+
UnionInputType
1597+
( Data.Functor.Product.Pair
1598+
( Control.Applicative.Const (mx <> my) )
1599+
( Op (either fx fy) )
1600+
)
15901601

1591-
-- As of base 4.12, we can use :*: to derive this instance automatically
1592-
instance Monoid (UnionInputType a) where
1593-
mempty = UnionInputType (Data.Functor.Product.Pair mempty mempty)
1602+
infixr 5 >|<
15941603

15951604
inputUnion :: UnionInputType a -> InputType a
15961605
inputUnion ( UnionInputType ( Data.Functor.Product.Pair ( Control.Applicative.Const fields ) ( Op embedF ) ) ) =
15971606
InputType
15981607
{ embed =
1599-
embedder
1608+
embedF
16001609
, declared =
16011610
Union fields
16021611
}
1603-
where
1604-
embedder = fromMaybe (errorWithoutStackTrace unmatched) . Data.Monoid.getFirst . embedF
1605-
unmatched = "inputUnion: UnionInputType is incomplete"
16061612

16071613
inputConstructorWith
16081614
:: Text
1609-
-> InputType b
1610-
-> (a -> Maybe b)
1615+
-> InputType a
16111616
-> UnionInputType a
1612-
inputConstructorWith name inputType projector = UnionInputType $
1617+
inputConstructorWith name inputType = UnionInputType $
16131618
Data.Functor.Product.Pair
16141619
( Control.Applicative.Const
16151620
( Dhall.Map.singleton
16161621
name
1617-
(declared inputType)
1622+
( declared inputType )
16181623
)
16191624
)
1620-
( Op
1621-
( Data.Monoid.First . fmap (embed inputType) . projector )
1625+
( Op ( embed inputType )
16221626
)
16231627

16241628
inputConstructor
1625-
:: Inject b
1629+
:: Inject a
16261630
=> Text
1627-
-> (a -> Maybe b)
16281631
-> UnionInputType a
16291632
inputConstructor name = inputConstructorWith name inject

0 commit comments

Comments
 (0)