summaryrefslogtreecommitdiff
path: root/src/Propellor/Types
diff options
context:
space:
mode:
authorJoey Hess2016-03-08 17:54:49 -0400
committerJoey Hess2016-03-08 17:54:49 -0400
commit61a1ba8ff1fa496af24d22986057a7607ae55ff1 (patch)
treea8ceb1621f4f2cf74892bcec2977dc72135df851 /src/Propellor/Types
parent4dab5fd328fc04ed006f32014330dac2621f0385 (diff)
make it a type error to intersect two OS lists if the result is empty
Diffstat (limited to 'src/Propellor/Types')
-rw-r--r--src/Propellor/Types/OS/Typelevel.hs15
1 files changed, 11 insertions, 4 deletions
diff --git a/src/Propellor/Types/OS/Typelevel.hs b/src/Propellor/Types/OS/Typelevel.hs
index 82f3a426..879259df 100644
--- a/src/Propellor/Types/OS/Typelevel.hs
+++ b/src/Propellor/Types/OS/Typelevel.hs
@@ -43,9 +43,8 @@ freeBSD = typeOS OSFreeBSD
typeOS :: SupportedOS -> OSList os
typeOS o = OSList [o]
--- FIXME, should type check
--- foo :: OSList '[OSDebian, OSFreeBSD]
--- foo = (debian `combineSupportedOS` freeBSD ) `intersectSupportedOS` unixlike
+foo :: OSList '[OSDebian, OSFreeBSD]
+foo = (debian `combineSupportedOS` freeBSD ) `intersectSupportedOS` unixlike
-- | Combines two lists of supported OS's, yielding a list with the
-- contents of both.
@@ -63,12 +62,20 @@ type instance ConcatOSList (a ': rest) list2 = a ': ConcatOSList rest list2
-- | The intersection between two lists of supported OS's.
intersectSupportedOS
- :: (r ~ IntersectOSList l1 l2)
+ :: (r ~ IntersectOSList l1 l2, CannotCombineOS l1 l2 r ~ CanCombineOS)
=> OSList l1
-> OSList l2
-> OSList r
intersectSupportedOS (OSList l1) (OSList l2) = OSList (filter (`elem` l2) l1)
+-- | Detect intersection of two lists that don't have any common OS.
+--
+-- The name of this was chosen to make type errors a more understandable.
+type family CannotCombineOS (list1 :: [a]) (list2 :: [a]) (listr :: [a]) :: CheckIntersection
+type instance CannotCombineOS l1 l2 '[] = 'CannotCombineOS
+type instance CannotCombineOS l1 l2 (a ': rest) = 'CanCombineOS
+data CheckIntersection = CannotCombineOS | CanCombineOS
+
-- | Type level intersection for OSList
type family IntersectOSList (list1 :: [a]) (list2 :: [a]) :: [a]
type instance IntersectOSList '[] list2 = '[]