I need to create an instance of Show
of a somewhat complicated type that represents a C++ function. The "serialization" gives me a Haskell interpretation of the said function.
It works as I wish but it looks utterly horrible, with the string concatenations, point-free conversions and nested let bindings. How could I improve readability of the code?
instance Show Function where
show (Function templateArgs returnT fname fArgs) =
let toLowerIfPolymorphic argName =
let lcArg = strToLower argName in
if lcArg `elem` (map snd templateArgs)
then lcArg
else id argName in
concat [
fname, " :: (",
intercalate ", " (
filter (/="") . map (
\(concept, tIdent) ->
if not $ elem concept ["Any", "typename", "class"]
then concept ++ " " ++ strToLower tIdent
else ""
) $ templateArgs
), ") => ",
intercalate " -> " (
map toLowerIfPolymorphic . map (show . fst) $ fArgs
),
(if not $ null fArgs then " -> " else ""),
toLowerIfPolymorphic . show $ returnT
]
The Function
is:
data Function = Function {
funcTemplateArgs :: [(Concept, Identifier)],
funcReturnT :: CppType,
funcName :: String,
funcArgs :: [(CppType, Identifier)]
}
CppType
is basically a sum-type representing Scalar
and Parameterzied
types. Just synonyms for tuples. Concept
/ Identifier
is a String
synonym. Everything is an instance of Show
.
Also I find the if condition then f else id
very strange. "Do nothing if false" is somewhat silly.