Cleaner Alternative to Extensive Pattern Matching in Haskell

后端 未结 5 1419
旧巷少年郎
旧巷少年郎 2021-02-07 01:13

Right now, I have some code that essentially works like this:

data Expression 
    = Literal Bool 
    | Variable String
    | Not Expression 
    | Or Expressio         


        
5条回答
  •  我寻月下人不归
    2021-02-07 01:53

    Carrying on with your Binary Op Expression Expression idea, we could have the datatype:

    data Expression
        = Literal Bool
        | Variable String
        | Not Expression
        | Binary Op Expression Expression
        deriving Eq
    
    data Op = Or | And deriving Eq
    

    And an auxiliary function

    {-# LANGUAGE ViewPatterns #-}
    
    simplifyBinary  :: Op -> Expression -> Expression -> Expression
    simplifyBinary  binop (simplify -> leftexp) (simplify -> rightexp) =
        case oneway binop leftexp rightexp ++ oneway binop rightexp leftexp of
            simplified : _ -> simplified
            []             -> Binary binop leftexp rightexp
      where
        oneway :: Op -> Expression -> Expression -> [Expression]
        oneway And (Literal False) _ = [Literal False]
        oneway Or  (Literal True)  _ = [Literal True]
        -- more cases here
        oneway _   _               _ = []
    

    The idea is that you would put the simplification cases in oneway and then simplifyBinary would take care of reversing the arguments, to avoid having to write the symmetric cases.

提交回复
热议问题