convertProofTerm :: M -> ProofTerm
convertProofTerm m =
  case m of
  M [] (R (RConst "var") [mOBS, mOPT]) ->
    let (mv, mOPT') = splitBinder mOPT
        (_, mOBS')  = splitBinder mOBS
     in VarIntro (convertSequent mOBS') mv (convertProofTerm mOPT')
  M [] (R (RConst "assumption;") [mBS, mPhi, mPT]) ->
    let (mv, mPT') = splitBinder mPT in
    Assumption (convertSequent mBS) (convertProp mPhi) mv (convertProofTerm mPT')
  M [] (R (RConst ";") [mBS, mBT, mPT1, mPT2]) ->
    let (mv, mPT2') = splitBinder mPT2 in
    Seq (convertSequent mBS) (convertSequent mBT)
        (convertProofTerm mPT1) mv (convertProofTerm mPT2')
  M [] (R (RConst "copy") [mPhi, mRef]) ->
    Copy (convertProp mPhi) (convertVarName mRef)
  M [] (R (RConst "top_i") []) -> TopI
  M [] (R (RConst "con_i") [mPA, mPB, mRefA, mRefB]) ->
    ConI (convertProp mPA) (convertProp mPB)
         (convertVarName mRefA) (convertVarName mRefB)
  M [] (R (RConst "con_e1") [mPA, mPB, mRef]) ->
    ConE1 (convertProp mPA) (convertProp mPB) (convertVarName mRef)
  M [] (R (RConst "con_e2") [mPA, mPB, mRef]) ->
    ConE2 (convertProp mPA) (convertProp mPB) (convertVarName mRef)
  M [] (R (RConst "dis_e") [mPA, mPB, mPC, mRef1, mRef2, mRef3]) ->
    DisE (convertProp mPA) (convertProp mPB) (convertProp mPC)
         (convertVarName mRef1) (convertVarName mRef2) (convertVarName mRef3)
  M [] (R (RConst "dis_i1") [mPA, mPB, mRef]) ->
    DisI1 (convertProp mPA) (convertProp mPB) (convertVarName mRef)
  M [] (R (RConst "dis_i2") [mPA, mPB, mRef]) ->
    DisI2 (convertProp mPA) (convertProp mPB) (convertVarName mRef)
  M [] (R (RConst "imp_i") [mPA, mPB, mRef]) ->
    ImpI (convertProp mPA) (convertProp mPB) (convertVarName mRef)
  M [] (R (RConst "imp_e") [mPA, mPB, mRef1, mRef2]) ->
    ImpE (convertProp mPA) (convertProp mPB)
         (convertVarName mRef1) (convertVarName mRef2)
  M [] (R (RConst "neg_i") [mPA, mRef]) ->
    NegI (convertProp mPA) (convertVarName mRef)
  M [] (R (RConst "neg_e") [mPA, mRef1, mRef2]) ->
    NegE (convertProp mPA) (convertVarName mRef1) (convertVarName mRef2)
  M [] (R (RConst "bot_e") [mPA, mRef]) ->
    BotE (convertProp mPA) (convertVarName mRef)
  M [] (R (RConst "all_i") [mOPA, mRef]) ->
    let (mv, mOPA') = splitBinder mOPA in
    AllI mv (convertProp mOPA') (convertVarName mRef)
  M [] (R (RConst "all_e") [mOPA, mT, mRef]) ->
    let (mv, mOPA') = splitBinder mOPA in
    AllE mv (convertProp mOPA') (convertTerm mT) (convertVarName mRef)
  M [] (R (RConst "exi_i") [mOPA, mT, mRef]) ->
    let (mv, mOPA') = splitBinder mOPA in
    ExiI mv (convertProp mOPA') (convertTerm mT) (convertVarName mRef)
  M [] (R (RConst "exi_e") [mOPA, mPB, mRef1, mRef2]) ->
    let (mv, mOPA') = splitBinder mOPA in
    ExiE mv (convertProp mOPA') (convertProp mPB)
         (convertVarName mRef1) (convertVarName mRef2)
  M [] (R (RConst "eq_i") [mT]) ->
    EqI (convertTerm mT)
  M [] (R (RConst "eq_e") [mS, mT, mOPA, mRef1, mRef2]) ->
    let (mv, mOPA') = splitBinder mOPA in
    EqE (convertTerm mS) (convertTerm mT) mv (convertProp mOPA')
        (convertVarName mRef1) (convertVarName mRef2)
  M [] (R (RConst "lem") [mPA]) ->
    LEM (convertProp mPA)
  M [] (R (RConst "nne") [mPA, mRef]) ->
    NNE (convertProp mPA) (convertVarName mRef)
  M [] (R (RConst "pbc") [mPA, mRef]) ->
    PBC (convertProp mPA) (convertVarName mRef)
  M [] (R (RConst "mt") [mPA, mPB, mRef1, mRef2]) ->
    MT (convertProp mPA) (convertProp mPB) (convertVarName mRef1) (convertVarName mRef2)
  M [] (R (RConst "nni") [mPA, mRef]) ->
    NNI (convertProp mPA) (convertVarName mRef)
  M (_:_) _ -> error $ concat ["Encountered unexpected open proof term."]
  M [] (R (RVar hole (A bindings p)) args) ->
    Hole (convertProofType p)
         hole
         (zipWith convertObj (map (bindTy . convertHypothesis) bindings) args)
  M _ (R root args) ->
    error $ concat ["Encountered unknown proof-term with root '"
                   ,show root, "' and "
                   ,show $ length args
                   ," arguments."]
convertProofTerm :: M -> ProofTerm
convertProofTerm m =
  case m of
  M [] (R (RConst "var") [mOBS, mOPT]) ->
    let (mv, mOPT') = splitBinder mOPT
        (_, mOBS')  = splitBinder mOBS
     in VarIntro (convertSequent mOBS') mv (convertProofTerm mOPT')
  M [] (R (RConst "assumption;") [mBS, mPhi, mPT]) ->
    let (mv, mPT') = splitBinder mPT in
    Assumption (convertSequent mBS) (convertProp mPhi) mv (convertProofTerm mPT')
  M [] (R (RConst ";") [mBS, mBT, mPT1, mPT2]) ->
    let (mv, mPT2') = splitBinder mPT2 in
    Seq (convertSequent mBS) (convertSequent mBT)
        (convertProofTerm mPT1) mv (convertProofTerm mPT2')
  M [] (R (RConst "copy") [mPhi, mRef]) ->
    Copy (convertProp mPhi) (convertVarName mRef)
  M [] (R (RConst "top_i") []) -> TopI
  M [] (R (RConst "con_i") [mPA, mPB, mRefA, mRefB]) ->
    ConI (convertProp mPA) (convertProp mPB)
         (convertVarName mRefA) (convertVarName mRefB)
  M [] (R (RConst "con_e1") [mPA, mPB, mRef]) ->
    ConE1 (convertProp mPA) (convertProp mPB) (convertVarName mRef)
  M [] (R (RConst "con_e2") [mPA, mPB, mRef]) ->
    ConE2 (convertProp mPA) (convertProp mPB) (convertVarName mRef)
  M [] (R (RConst "dis_e") [mPA, mPB, mPC, mRef1, mRef2, mRef3]) ->
    DisE (convertProp mPA) (convertProp mPB) (convertProp mPC)
         (convertVarName mRef1) (convertVarName mRef2) (convertVarName mRef3)
  M [] (R (RConst "dis_i1") [mPA, mPB, mRef]) ->
    DisI1 (convertProp mPA) (convertProp mPB) (convertVarName mRef)
  M [] (R (RConst "dis_i2") [mPA, mPB, mRef]) ->
    DisI2 (convertProp mPA) (convertProp mPB) (convertVarName mRef)
  M [] (R (RConst "imp_i") [mPA, mPB, mRef]) ->
    ImpI (convertProp mPA) (convertProp mPB) (convertVarName mRef)
  M [] (R (RConst "imp_e") [mPA, mPB, mRef1, mRef2]) ->
    ImpE (convertProp mPA) (convertProp mPB)
         (convertVarName mRef1) (convertVarName mRef2)
  M [] (R (RConst "neg_i") [mPA, mRef]) ->
    NegI (convertProp mPA) (convertVarName mRef)
  M [] (R (RConst "neg_e") [mPA, mRef1, mRef2]) ->
    NegE (convertProp mPA) (convertVarName mRef1) (convertVarName mRef2)
  M [] (R (RConst "bot_e") [mPA, mRef]) ->
    BotE (convertProp mPA) (convertVarName mRef)
  M [] (R (RConst "all_i") [mOPA, mRef]) ->
    let (mv, mOPA') = splitBinder mOPA in
    AllI mv (convertProp mOPA') (convertVarName mRef)
  M [] (R (RConst "all_e") [mOPA, mT, mRef]) ->
    let (mv, mOPA') = splitBinder mOPA in
    AllE mv (convertProp mOPA') (convertTerm mT) (convertVarName mRef)
  M [] (R (RConst "exi_i") [mOPA, mT, mRef]) ->
    let (mv, mOPA') = splitBinder mOPA in
    ExiI mv (convertProp mOPA') (convertTerm mT) (convertVarName mRef)
  M [] (R (RConst "exi_e") [mOPA, mPB, mRef1, mRef2]) ->
    let (mv, mOPA') = splitBinder mOPA in
    ExiE mv (convertProp mOPA') (convertProp mPB)
         (convertVarName mRef1) (convertVarName mRef2)
  M [] (R (RConst "eq_i") [mT]) ->
    EqI (convertTerm mT)
  M [] (R (RConst "eq_e") [mS, mT, mOPA, mRef1, mRef2]) ->
    let (mv, mOPA') = splitBinder mOPA in
    EqE (convertTerm mS) (convertTerm mT) mv (convertProp mOPA')
        (convertVarName mRef1) (convertVarName mRef2)
  M [] (R (RConst "lem") [mPA]) ->
    LEM (convertProp mPA)
  M [] (R (RConst "nne") [mPA, mRef]) ->
    NNE (convertProp mPA) (convertVarName mRef)
  M [] (R (RConst "pbc") [mPA, mRef]) ->
    PBC (convertProp mPA) (convertVarName mRef)
  M [] (R (RConst "mt") [mPA, mPB, mRef1, mRef2]) ->
    MT (convertProp mPA) (convertProp mPB) (convertVarName mRef1) (convertVarName mRef2)
  M [] (R (RConst "nni") [mPA, mRef]) ->
    NNI (convertProp mPA) (convertVarName mRef)
  M (_:_) _ -> error $ concat ["Encountered unexpected open proof term."]
  M [] (R (RVar hole (A bindings p)) args) ->
    Hole (convertProofType p)
         hole
         (zipWith convertObj (map (bindTy . convertHypothesis) bindings) args)
  M _ (R root args) ->
    error $ concat ["Encountered unknown proof-term with root '"
                   ,show root, "' and "
                   ,show $ length args
                   ," arguments."]
convertProofTerm m =
  case m of
  M [] (R (RConst "var") [mOBS, mOPT]) ->
    let (mv, mOPT') = splitBinder mOPT
        (_, mOBS')  = splitBinder mOBS
     in VarIntro (convertSequent mOBS') mv (convertProofTerm mOPT')
  M [] (R (RConst "assumption;") [mBS, mPhi, mPT]) ->
    let (mv, mPT') = splitBinder mPT in
    Assumption (convertSequent mBS) (convertProp mPhi) mv (convertProofTerm mPT')
  M [] (R (RConst ";") [mBS, mBT, mPT1, mPT2]) ->
    let (mv, mPT2') = splitBinder mPT2 in
    Seq (convertSequent mBS) (convertSequent mBT)
        (convertProofTerm mPT1) mv (convertProofTerm mPT2')
  M [] (R (RConst "copy") [mPhi, mRef]) ->
    Copy (convertProp mPhi) (convertVarName mRef)
  M [] (R (RConst "top_i") []) -> TopI
  M [] (R (RConst "con_i") [mPA, mPB, mRefA, mRefB]) ->
    ConI (convertProp mPA) (convertProp mPB)
         (convertVarName mRefA) (convertVarName mRefB)
  M [] (R (RConst "con_e1") [mPA, mPB, mRef]) ->
    ConE1 (convertProp mPA) (convertProp mPB) (convertVarName mRef)
  M [] (R (RConst "con_e2") [mPA, mPB, mRef]) ->
    ConE2 (convertProp mPA) (convertProp mPB) (convertVarName mRef)
  M [] (R (RConst "dis_e") [mPA, mPB, mPC, mRef1, mRef2, mRef3]) ->
    DisE (convertProp mPA) (convertProp mPB) (convertProp mPC)
         (convertVarName mRef1) (convertVarName mRef2) (convertVarName mRef3)
  M [] (R (RConst "dis_i1") [mPA, mPB, mRef]) ->
    DisI1 (convertProp mPA) (convertProp mPB) (convertVarName mRef)
  M [] (R (RConst "dis_i2") [mPA, mPB, mRef]) ->
    DisI2 (convertProp mPA) (convertProp mPB) (convertVarName mRef)
  M [] (R (RConst "imp_i") [mPA, mPB, mRef]) ->
    ImpI (convertProp mPA) (convertProp mPB) (convertVarName mRef)
  M [] (R (RConst "imp_e") [mPA, mPB, mRef1, mRef2]) ->
    ImpE (convertProp mPA) (convertProp mPB)
         (convertVarName mRef1) (convertVarName mRef2)
  M [] (R (RConst "neg_i") [mPA, mRef]) ->
    NegI (convertProp mPA) (convertVarName mRef)
  M [] (R (RConst "neg_e") [mPA, mRef1, mRef2]) ->
    NegE (convertProp mPA) (convertVarName mRef1) (convertVarName mRef2)
  M [] (R (RConst "bot_e") [mPA, mRef]) ->
    BotE (convertProp mPA) (convertVarName mRef)
  M [] (R (RConst "all_i") [mOPA, mRef]) ->
    let (mv, mOPA') = splitBinder mOPA in
    AllI mv (convertProp mOPA') (convertVarName mRef)
  M [] (R (RConst "all_e") [mOPA, mT, mRef]) ->
    let (mv, mOPA') = splitBinder mOPA in
    AllE mv (convertProp mOPA') (convertTerm mT) (convertVarName mRef)
  M [] (R (RConst "exi_i") [mOPA, mT, mRef]) ->
    let (mv, mOPA') = splitBinder mOPA in
    ExiI mv (convertProp mOPA') (convertTerm mT) (convertVarName mRef)
  M [] (R (RConst "exi_e") [mOPA, mPB, mRef1, mRef2]) ->
    let (mv, mOPA') = splitBinder mOPA in
    ExiE mv (convertProp mOPA') (convertProp mPB)
         (convertVarName mRef1) (convertVarName mRef2)
  M [] (R (RConst "eq_i") [mT]) ->
    EqI (convertTerm mT)
  M [] (R (RConst "eq_e") [mS, mT, mOPA, mRef1, mRef2]) ->
    let (mv, mOPA') = splitBinder mOPA in
    EqE (convertTerm mS) (convertTerm mT) mv (convertProp mOPA')
        (convertVarName mRef1) (convertVarName mRef2)
  M [] (R (RConst "lem") [mPA]) ->
    LEM (convertProp mPA)
  M [] (R (RConst "nne") [mPA, mRef]) ->
    NNE (convertProp mPA) (convertVarName mRef)
  M [] (R (RConst "pbc") [mPA, mRef]) ->
    PBC (convertProp mPA) (convertVarName mRef)
  M [] (R (RConst "mt") [mPA, mPB, mRef1, mRef2]) ->
    MT (convertProp mPA) (convertProp mPB) (convertVarName mRef1) (convertVarName mRef2)
  M [] (R (RConst "nni") [mPA, mRef]) ->
    NNI (convertProp mPA) (convertVarName mRef)
  M (_:_) _ -> error $ concat ["Encountered unexpected open proof term."]
  M [] (R (RVar hole (A bindings p)) args) ->
    Hole (convertProofType p)
         hole
         (zipWith convertObj (map (bindTy . convertHypothesis) bindings) args)
  M _ (R root args) ->
    error $ concat ["Encountered unknown proof-term with root '"
                   ,show root, "' and "
                   ,show $ length args
                   ," arguments."]