문제

I want format this function:

getEnv :: [Func] -> ([Char] -> RetType)
getEnv [] = (\_ -> undefined)
getEnv ((Func (RetTypeType t) (Ident fname) _ _):fs) = (\x -> if x == fname then t else getEnv fs)

The problem is caused by a long pattern matching, and for now I don't want to change the names of constructors. Also the right part of the function at the third line is not easy to formatting for me.

Although is not matter of life or death, I'm curios how you format this code. Thanks.

도움이 되었습니까?

해결책

Basically, you have two possibilities:

Something like this:

getEnv ((Func 
          (RetTypeType t) 
          (Ident fname) _ _)
       :fs) 
    = (\x -> if x == fname then t else getEnv fs)

or you can use pattern guards:

getEnv (h:fs)
  | Func a b _ _ <- h,
    Rectype t <- a,
    Ident fname <- b 
  = (\x -> if x == fname then t else getEnv fs)

You could furthermore avoid the lambda:

getEnv (h:fs) x
  | Func a b _ _ <- h,
    Rectype t <- a,
    Ident fname <- b 
  = if x == fname then t else getEnv fs

The downside with "open" pattern guards may be that the compiler cannot decide anymore whether your patterns are exhaustive.

As @leftaroundabout points out, we can put it even more clearly thus:

getEnv (h:fs) x
  | Func a b _ _ <- h,
    Rectype t <- a,
    Ident fname <- b,
    x == fname         = t
  | otherwise          = getEnv fs

This will also let the compiler know that all possible forms of the head of the list are covered, so this I'd term the most preferred way to do it.

다른 팁

I would usually simply do

getEnv :: [Func] -> ([Char] -> RetType)
getEnv [] = (\_ -> undefined)

getEnv ((Func (RetTypeType t) (Ident fname) _ _):fs) 
          = \x -> if x == fname then t else getEnv fs

However I'd be inclined if I was doing a lot of that to use record syntax

data Func = Func {returnTypeType :: RetTypeType,
                  identifier :: Ident,
                  .... }
data RetTypeType = RetTypeType {unRetTypeType :: RetType}
data Ident = Ident {unIdent:: String}

so I could write

getEnv :: [Func] -> ([Char] -> RetType)
getEnv [] = (\_ -> undefined)
getEnv (f:fs) = \x -> if x == ident f 
                      then unRetTypeType.returnTypeType $ f 
                       else getEnv fs

First of all, I try to keep patterns simple. Usually it's just one constructor with variables or underscores as it's arguments. Exception: built-in constructors like (:) or (,) don't count. So, if you have that kind of pattern-matching, I think you are doing something wrong.

Secondly, I would just split the line at '=' and be happy.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top