mapSign :: CS.Sign f e -> Result (OS.Sign, [Named Axiom])
mapSign csig = let
  esorts = emptySortSet csig
  srel = sortRel csig
  (eqs, subss) = eqAndSubsorts False srel
  (isos, rels) = singleAndRelatedSorts srel
  disjSorts = concatMap (\ l -> case l of
    _ : _ : _ -> [makeNamed ("disjoint " ++ show l) $ mkMisc Disjoint l]
    _ -> []) . sequence $ map (: []) isos ++ map (keepMaximals csig) rels
  ss = sortSet csig
  nsorts = Set.difference ss esorts
  mkMisc ed l = PlainAxiom (Misc []) $ ListFrameBit (Just $ EDRelation ed)
          $ ExpressionBit $ map toACE l
  eqSorts = map (\ es -> makeNamed ("equal sorts " ++ show es)
                 $ mkMisc Equivalent es) eqs
  subSens = map (\ (s, ts) -> makeNamed
    ("subsort " ++ show s ++ " of " ++ show ts) $ toSC s ts) subss
  nonEmptySens = map (\ s -> mkIndi True s [s]) $ Set.toList nsorts
  sortSens = eqSorts ++ disjSorts ++ subSens ++ nonEmptySens
  mkIndi b i ts = makeNamed
        ("individual " ++ show i ++ " of class " ++ showDoc ts "")
        $ PlainAxiom (SimpleEntity $ Entity NamedIndividual
        $ idToAnonIRI b i)
        $ ListFrameBit (Just Types) $ ExpressionBit
        $ map toACE ts
  om = opMap csig
  keepMaxs = keepMaximals csig
  mk s i = mkObjEnt s i (-1)
  toSC i = toSubClass i . map toC
  toIris = Set.map idToIRI
  (cs, ncs) = MapSet.partition (null . opArgs) om
  (sos, os) = MapSet.partition isSingleArgOp ncs
  (props, nps) = MapSet.partition (null . predArgs) pm
  (sps, rps) = MapSet.partition (isSingle . predArgs) nps
  (bps, ps) = MapSet.partition isBinPredType rps
  pm = predMap csig
  osig = OS.emptySign
    { concepts = toIris $ Set.unions
      [ ss, MapSet.keysSet sps, MapSet.keysSet props
      , MapSet.keysSet os, MapSet.keysSet ps]
    , objectProperties = Set.unions
      [ toIris $ Set.union (MapSet.keysSet sos) $ MapSet.keysSet bps
      , getPropNames predArgs ps, getPropNames opArgs os ]
    , individuals = toIris $ MapSet.keysSet cs
    }
  in do
  s1 <- Map.foldWithKey (\ i s ml -> do
      l <- ml
      return $ mkIndi False i
        (keepMinimals csig id $ map opRes $ Set.toList s) : l)
    (return sortSens) (MapSet.toMap cs)
  s2 <- Map.foldWithKey (\ i s ml -> do
    l <- ml
    let sl = Set.toList s
        mki = mk "plain function " i
    case (keepMaxs $ concatMap opArgs sl, keepMaxs $ map opRes sl) of
      ([a], [r]) -> return
         $ [ mki " character" $ ListFrameBit Nothing
             $ ObjectCharacteristics [([], Functional)]
           , mki " domain" $ mkDR ADomain a, mki " range" $ mkDR ARange r]
         ++ l
      (as, rs) -> fail $ "CASL2OWL.mapSign2: " ++ show i ++ " args: "
                   ++ show as ++ " resulttypes: " ++ show rs)
    (return s1) (MapSet.toMap sos)
  s3 <- Map.foldWithKey (\ i s ml -> do
    l <- ml
    let mkp = mk "binary predicate " i
    pTy <- commonPredType csig s
    case predArgs pTy of
      [a, r] -> return
         $ [mkp " domain" $ mkDR ADomain a, mkp " range" $ mkDR ARange r]
         ++ l
      ts -> fail $ "CASL2OWL.mapSign3: " ++ show i ++ " types: " ++ show ts)
    (return s2) (MapSet.toMap bps)
  s4 <- Map.foldWithKey (\ i s ml ->
     case keepMaxs $ concatMap predArgs $ Set.toList s of
       [r] -> do
         l <- ml
         return $ makeNamed ("plain predicate " ++ show i) (toSC i [r]) : l
       ts -> fail $ "CASL2OWL.mapSign4: " ++ show i ++ " types: " ++ show ts)
     (return s3) (MapSet.toMap sps)
  s5 <- Map.foldWithKey (\ i s ml -> do
     l <- ml
     ot <- commonOpType csig s
     return $ getPropSens i (opArgs ot) (Just $ opRes ot) ++ l
     ) (return s4) (MapSet.toMap os)
  s6 <- Map.foldWithKey (\ i s ml -> do
     l <- ml
     pt <- commonPredType csig s
     return $ getPropSens i (predArgs pt) Nothing ++ l
     ) (return s5) (MapSet.toMap ps)
  return (osig, s6)

{- binary predicates and single argument functions should become
   objectProperties.
   Serge also turned constructors into concepts.
   How to treat multi-argument predicates and functions?
   Maybe create tuple concepts?
-}
mapSign :: CS.Sign f e -> Result (OS.Sign, [Named Axiom])
mapSign csig = let
  esorts = emptySortSet csig
  srel = sortRel csig
  (eqs, subss) = eqAndSubsorts False srel
  (isos, rels) = singleAndRelatedSorts srel
  disjSorts = concatMap (\ l -> case l of
    _ : _ : _ -> [makeNamed ("disjoint " ++ show l) $ mkMisc Disjoint l]
    _ -> []) . sequence $ map (: []) isos ++ map (keepMaximals csig) rels
  ss = sortSet csig
  nsorts = Set.difference ss esorts
  mkMisc ed l = PlainAxiom (Misc []) $ ListFrameBit (Just $ EDRelation ed)
          $ ExpressionBit $ map toACE l
  eqSorts = map (\ es -> makeNamed ("equal sorts " ++ show es)
                 $ mkMisc Equivalent es) eqs
  subSens = map (\ (s, ts) -> makeNamed
    ("subsort " ++ show s ++ " of " ++ show ts) $ toSC s ts) subss
  nonEmptySens = map (\ s -> mkIndi True s [s]) $ Set.toList nsorts
  sortSens = eqSorts ++ disjSorts ++ subSens ++ nonEmptySens
  mkIndi b i ts = makeNamed
        ("individual " ++ show i ++ " of class " ++ showDoc ts "")
        $ PlainAxiom (SimpleEntity $ Entity NamedIndividual
        $ idToAnonIRI b i)
        $ ListFrameBit (Just Types) $ ExpressionBit
        $ map toACE ts
  om = opMap csig
  keepMaxs = keepMaximals csig
  mk s i = mkObjEnt s i (-1)
  toSC i = toSubClass i . map toC
  toIris = Set.map idToIRI
  (cs, ncs) = MapSet.partition (null . opArgs) om
  (sos, os) = MapSet.partition isSingleArgOp ncs
  (props, nps) = MapSet.partition (null . predArgs) pm
  (sps, rps) = MapSet.partition (isSingle . predArgs) nps
  (bps, ps) = MapSet.partition isBinPredType rps
  pm = predMap csig
  osig = OS.emptySign
    { concepts = toIris $ Set.unions
      [ ss, MapSet.keysSet sps, MapSet.keysSet props
      , MapSet.keysSet os, MapSet.keysSet ps]
    , objectProperties = Set.unions
      [ toIris $ Set.union (MapSet.keysSet sos) $ MapSet.keysSet bps
      , getPropNames predArgs ps, getPropNames opArgs os ]
    , individuals = toIris $ MapSet.keysSet cs
    }
  in do
  s1 <- Map.foldWithKey (\ i s ml -> do
      l <- ml
      return $ mkIndi False i
        (keepMinimals csig id $ map opRes $ Set.toList s) : l)
    (return sortSens) (MapSet.toMap cs)
  s2 <- Map.foldWithKey (\ i s ml -> do
    l <- ml
    let sl = Set.toList s
        mki = mk "plain function " i
    case (keepMaxs $ concatMap opArgs sl, keepMaxs $ map opRes sl) of
      ([a], [r]) -> return
         $ [ mki " character" $ ListFrameBit Nothing
             $ ObjectCharacteristics [([], Functional)]
           , mki " domain" $ mkDR ADomain a, mki " range" $ mkDR ARange r]
         ++ l
      (as, rs) -> fail $ "CASL2OWL.mapSign2: " ++ show i ++ " args: "
                   ++ show as ++ " resulttypes: " ++ show rs)
    (return s1) (MapSet.toMap sos)
  s3 <- Map.foldWithKey (\ i s ml -> do
    l <- ml
    let mkp = mk "binary predicate " i
    pTy <- commonPredType csig s
    case predArgs pTy of
      [a, r] -> return
         $ [mkp " domain" $ mkDR ADomain a, mkp " range" $ mkDR ARange r]
         ++ l
      ts -> fail $ "CASL2OWL.mapSign3: " ++ show i ++ " types: " ++ show ts)
    (return s2) (MapSet.toMap bps)
  s4 <- Map.foldWithKey (\ i s ml ->
     case keepMaxs $ concatMap predArgs $ Set.toList s of
       [r] -> do
         l <- ml
         return $ makeNamed ("plain predicate " ++ show i) (toSC i [r]) : l
       ts -> fail $ "CASL2OWL.mapSign4: " ++ show i ++ " types: " ++ show ts)
     (return s3) (MapSet.toMap sps)
  s5 <- Map.foldWithKey (\ i s ml -> do
     l <- ml
     ot <- commonOpType csig s
     return $ getPropSens i (opArgs ot) (Just $ opRes ot) ++ l
     ) (return s4) (MapSet.toMap os)
  s6 <- Map.foldWithKey (\ i s ml -> do
     l <- ml
     pt <- commonPredType csig s
     return $ getPropSens i (predArgs pt) Nothing ++ l
     ) (return s5) (MapSet.toMap ps)
  return (osig, s6)

{- binary predicates and single argument functions should become
   objectProperties.
   Serge also turned constructors into concepts.
   How to treat multi-argument predicates and functions?
   Maybe create tuple concepts?
-}
mapSign csig = let
  esorts = emptySortSet csig
  srel = sortRel csig
  (eqs, subss) = eqAndSubsorts False srel
  (isos, rels) = singleAndRelatedSorts srel
  disjSorts = concatMap (\ l -> case l of
    _ : _ : _ -> [makeNamed ("disjoint " ++ show l) $ mkMisc Disjoint l]
    _ -> []) . sequence $ map (: []) isos ++ map (keepMaximals csig) rels
  ss = sortSet csig
  nsorts = Set.difference ss esorts
  mkMisc ed l = PlainAxiom (Misc []) $ ListFrameBit (Just $ EDRelation ed)
          $ ExpressionBit $ map toACE l
  eqSorts = map (\ es -> makeNamed ("equal sorts " ++ show es)
                 $ mkMisc Equivalent es) eqs
  subSens = map (\ (s, ts) -> makeNamed
    ("subsort " ++ show s ++ " of " ++ show ts) $ toSC s ts) subss
  nonEmptySens = map (\ s -> mkIndi True s [s]) $ Set.toList nsorts
  sortSens = eqSorts ++ disjSorts ++ subSens ++ nonEmptySens
  mkIndi b i ts = makeNamed
        ("individual " ++ show i ++ " of class " ++ showDoc ts "")
        $ PlainAxiom (SimpleEntity $ Entity NamedIndividual
        $ idToAnonIRI b i)
        $ ListFrameBit (Just Types) $ ExpressionBit
        $ map toACE ts
  om = opMap csig
  keepMaxs = keepMaximals csig
  mk s i = mkObjEnt s i (-1)
  toSC i = toSubClass i . map toC
  toIris = Set.map idToIRI
  (cs, ncs) = MapSet.partition (null . opArgs) om
  (sos, os) = MapSet.partition isSingleArgOp ncs
  (props, nps) = MapSet.partition (null . predArgs) pm
  (sps, rps) = MapSet.partition (isSingle . predArgs) nps
  (bps, ps) = MapSet.partition isBinPredType rps
  pm = predMap csig
  osig = OS.emptySign
    { concepts = toIris $ Set.unions
      [ ss, MapSet.keysSet sps, MapSet.keysSet props
      , MapSet.keysSet os, MapSet.keysSet ps]
    , objectProperties = Set.unions
      [ toIris $ Set.union (MapSet.keysSet sos) $ MapSet.keysSet bps
      , getPropNames predArgs ps, getPropNames opArgs os ]
    , individuals = toIris $ MapSet.keysSet cs
    }
  in do
  s1 <- Map.foldWithKey (\ i s ml -> do
      l <- ml
      return $ mkIndi False i
        (keepMinimals csig id $ map opRes $ Set.toList s) : l)
    (return sortSens) (MapSet.toMap cs)
  s2 <- Map.foldWithKey (\ i s ml -> do
    l <- ml
    let sl = Set.toList s
        mki = mk "plain function " i
    case (keepMaxs $ concatMap opArgs sl, keepMaxs $ map opRes sl) of
      ([a], [r]) -> return
         $ [ mki " character" $ ListFrameBit Nothing
             $ ObjectCharacteristics [([], Functional)]
           , mki " domain" $ mkDR ADomain a, mki " range" $ mkDR ARange r]
         ++ l
      (as, rs) -> fail $ "CASL2OWL.mapSign2: " ++ show i ++ " args: "
                   ++ show as ++ " resulttypes: " ++ show rs)
    (return s1) (MapSet.toMap sos)
  s3 <- Map.foldWithKey (\ i s ml -> do
    l <- ml
    let mkp = mk "binary predicate " i
    pTy <- commonPredType csig s
    case predArgs pTy of
      [a, r] -> return
         $ [mkp " domain" $ mkDR ADomain a, mkp " range" $ mkDR ARange r]
         ++ l
      ts -> fail $ "CASL2OWL.mapSign3: " ++ show i ++ " types: " ++ show ts)
    (return s2) (MapSet.toMap bps)
  s4 <- Map.foldWithKey (\ i s ml ->
     case keepMaxs $ concatMap predArgs $ Set.toList s of
       [r] -> do
         l <- ml
         return $ makeNamed ("plain predicate " ++ show i) (toSC i [r]) : l
       ts -> fail $ "CASL2OWL.mapSign4: " ++ show i ++ " types: " ++ show ts)
     (return s3) (MapSet.toMap sps)
  s5 <- Map.foldWithKey (\ i s ml -> do
     l <- ml
     ot <- commonOpType csig s
     return $ getPropSens i (opArgs ot) (Just $ opRes ot) ++ l
     ) (return s4) (MapSet.toMap os)
  s6 <- Map.foldWithKey (\ i s ml -> do
     l <- ml
     pt <- commonPredType csig s
     return $ getPropSens i (predArgs pt) Nothing ++ l
     ) (return s5) (MapSet.toMap ps)
  return (osig, s6)

{- binary predicates and single argument functions should become
   objectProperties.
   Serge also turned constructors into concepts.
   How to treat multi-argument predicates and functions?
   Maybe create tuple concepts?
-}