{-# LANGUAGE NoMonomorphismRestriction #-} import Diagrams.Prelude import Diagrams.Backend.Cairo.CmdLine import Data.List import Data.Ord (comparing) import Data.Function (on) type D = Diagram Cairo R2 colors = [black, blue, red, yellow, green, orange, purple, brown] data Subset = Subset Int [Int] (Subset _ elts1) `isSubset` (Subset _ elts2) = all (`elem` elts2) elts1 subsetsBySize :: Int -> [[Subset]] subsetsBySize n = map (map (Subset n)) . groupBy ((==) `on` length) . sortBy (comparing length) . subsequences $ [1..n] drawSet :: Subset -> D drawSet (Subset n elts) = ( drawElts n elts # centerXY <> square # scaleX (fromIntegral n + 0.5) # scaleY 1.5 # dashing [0.2,0.2] 0 # lw 0.03 # namePoint (boundary (negateV unitY)) "B" # namePoint (boundary unitY) "T" # (show elts |>) ) # freeze drawElts n elts = hcat . map (\i -> if i `elem` elts then drawElt i else strutX 1) $ [1..n] drawElt e = square # fc (colors !! e) # lw 0.05 # freeze hasseDiagram n = setsD # drawConnections where setsD = vcat' with {sep = fromIntegral n} . map hasseRow . reverse $ subsets drawConnections = applyAll connections connections = concat $ zipWith connectSome subsets (tail subsets) connectSome subs1 subs2 = [ connect s1 s2 | s1 <- subs1 , s2 <- subs2 , s1 `isSubset` s2 ] connect (Subset _ elts1) (Subset _ elts2) = withName (show elts1 ||> "T") $ \p1 -> withName (show elts2 ||> "B") $ \p2 -> (<> stroke (fromVertices [p1,p2]) # lw 0.03) subsets = subsetsBySize n hasseRow = centerX . hcat' with {sep = 2} . map drawSet main = defaultMain (pad 1.1 $ hasseDiagram 4)