2012-06-20 73 views
4

我有两个函数,但其​​中一个函数只能从另一个函数中调用,所以我想内联辅助函数。我的代码如下所示:如何内嵌此功能?

data PoS = N | V | Adj | Adv | Phr 

posEntity :: Parser PoS 
posEntity = 
    do pos <- string "N." <|> 
       string "V." <|> 
       string "Adj." <|> 
       string "Adv." <|> 
       string "Phr." 
     return (posToPoS pos) 
    <?> "part of speech" 

posToPoS pos 
    | pos == "N." = N 
    | pos == "V." = V 
    | pos == "Adj." = Adj 
    | pos == "Adv." = Adv 
    | pos == "Phr." = Phr 

显然posToPoS应该内联,但我不能确定做这样的事情所需要的语法。

谢谢!

+0

这是编译器的工作。它会决定是否内联函数是一个好主意,如果它决定反对它,它可能会更好:) –

回答

4

GHC在优化时可能会自动内联。但是,要强制执行此操作,只需在代码的某处添加{-# INLINE posToPoS #-},最好在posToPoS的定义旁边。

为了使其成为本地,以便只有posEntity可以看到它,你想要一个where子句。定义它如下:

data PoS = N | V | Adj | Adv | Phr 

posEntity :: Parser PoS 
posEntity = 
    do pos <- string "N." <|> 
       string "V." <|> 
       string "Adj." <|> 
       string "Adv." <|> 
       string "Phr." 
     return (posToPoS pos) 
    <?> "part of speech" where 
     posToPoS pos 
      | pos == "N." = N 
      | pos == "V." = V 
      | pos == "Adj." = Adj 
      | pos == "Adv." = Adv 
      | pos == "Phr." = Phr 
+1

我希望它内联的范围原因,而不是优化。谢谢你的回答,但我不知道。 – Max

+0

@Max:你是什么意思,范围原因?您可以明确定义哪些功能是从模块导出的,哪些不是。 –

+0

我需要做一个不同的转换,具体取决于我正在解析的内容,如果有一堆不同的方法名称,例如posToPoS1,posToPoS2等,会很麻烦。所有这些方法都在同一个模块中,所以它在我需要转换完成的地方完成转换会很好。你可以在下面看到我的答案,以了解我的意思。 – Max

0

这是我想通了。对不起,如果我不清楚:

posEntity :: Parser PoS 
posEntity = 
    do pos <- string "N." <|> 
       string "V." <|> 
       string "Adj." <|> 
       string "Adv." <|> 
       string "Phr." 
     return (posToPoS pos) 
    <?> "part of speech" 
    where 
     posToPoS pos 
      | pos == "N." = N 
      | pos == "V." = V 
      | pos == "Adj." = Adj 
      | pos == "Adv." = Adv 
      | pos == "Phr." = Phr 
+0

heh。看起来你在编辑我的文章时输入了完全相同的答案。 – gereeter

+0

@greeter无论如何感谢:) – Max

8

您可以只在内嵌的定义字符串posToPos

posToPoS "N." = N 
posToPoS "V." = V 
-- ... etc 

或者,您可以用下面的方法直接解析器:

import Control.Applicative hiding (<|>) 

posEntity :: Parser PoS 
posEntity = 
    (string "N." *> pure N <|> 
    string "V." *> pure V <|> 
    string "Adj." *> pure Adj <|> 
    string "Adv." *> pure Adv <|> 
    string "Phr." *> pure Phr)<?> "part of speech" 

(您可能需要围绕string "foo" *> pure Foo部分括号,我忘记了运算符优先级是什么)

+0

甚至'N <$ string“N.”等 –

1

在您的例子,一个简单的case语句似乎更好的解决方案:

posEntity = 
    do pos <- string "N." <|> 
       string "V." <|> 
       string "Adj." <|> 
       string "Adv." <|> 
       string "Phr." 
     return $ case pos of 
        "N." -> N 
        "V." -> V 
        "Adj." -> Adj 
        "Adv." -> Adv 
        "Phr." -> Phr 
    <?> "part of speech" 

模式匹配一​​般都在平等的比较preferrable,如果你有选择。

+0

为什么downvote?这当然是一种明智的“内联”功能。 – leftaroundabout

+0

我把你提升为0.我喜欢你的解决方案比我的更好,但你能解释一下美元符号的用法吗?对不起,我对Haskell来说是非常新的。 – Max

+0

这只是为了将'return'从'case'块中分离出来。 – leftaroundabout