2013-04-27 53 views
2

我有data RegEx,我想实现instance Show a => Show RegEx a。这里是我的代码:如何在实施`实例`时隐藏帮助函数

showAtom :: Show a => RegEx a -> String 
showAtom (Lit x) = show x 
showAtom r  = "(" ++ (show r) ++ ")" 

instance Show a => Show (RegEx a) where 
    show (Lit x) = show [x] 
    show (Opt r) = (showAtom r) ++ "?" 
    show (Alt p q) = (showAtom p) ++ "|" ++ (showAtom q) 
    show (Seq p q) = (show p) ++ (show q) 
    show (Rep r) = (showAtom r) ++ "*" 

showAtom函数只是一个实现细节。我有什么方法可以隐藏它,只有在定义了instance后才能看到它?或者更好的是,只有在show内才能看到它。

回答

6

像这样的东西应该工作:

instance Show a => Show (RegEx a) where 
    show x = show' x 
     where 
     showAtom :: Show a => RegEx a -> String 
     showAtom (Lit x) = show x 
     showAtom r  = "(" ++ (show r) ++ ")" 

     show' (Lit x) = show [x] 
     show' (Opt r) = (showAtom r) ++ "?" 
     show' (Alt p q) = (showAtom p) ++ "|" ++ (showAtom q) 
     show' (Seq p q) = (show p) ++ (show q) 
     show' (Rep r) = (showAtom r) ++ "*" 

或者,你可以从模块的出口列表中排除showAtom

2

只是不在模块的export list中列出showAtom

+1

这只能将'showAtom'隐藏到其他模块。如果你还想将其从模块本身的其他部分隐藏起来,Mikhail Glushenkov的回答肯定是要走的路:) – gspr 2013-04-27 21:20:35

1

您可以通过不导出showAtom本地模块,但仍然可以使其在整个模块中可见 - 不仅仅是实例或show函数。

为了让本地的show功能,你需要使用letwhere,但那些都在函数参数列表中使用模式匹配时,适用于多种情况。您可以通过将模式匹配移动到case这样的语句来使其工作:

instance Show a => Show (RegEx a) where 
    show re = 
     let 
     showAtom :: Show a => RegEx a -> String 
     showAtom (Lit x) = show x 
     showAtom r  = "(" ++ (show r) ++ ")" 
     in 
     case re of 
      (Lit x) -> show [x] 
      (Opt r) -> (showAtom r) ++ "?" 
      (Alt p q) -> (showAtom p) ++ "|" ++ (showAtom q) 
      (Seq p q) -> (show p) ++ (show q) 
      (Rep r) -> (showAtom r) ++ "*"