【问题标题】:Invoking nested functions in Haskell在 Haskell 中调用嵌套函数
【发布时间】:2014-06-16 01:53:53
【问题描述】:

我在名为person 的函数中定义了一个名为initials 的函数,但我不知道如何在person 之外调用initials

main =
    --I attempted to print the output of the initials function here.
    (putStrLn ((person "firstName" "lastName") . initials)) --Not in scope: `initials'
    --If this function call worked correctly, the output would be "f.l.".

person firstName lastName =
    firstName ++ ["."] ++ lastName
    where
        fullName = firstName ++ " " ++ lastName
        firstInitial = firstName !! 0
        lastInitial = lastName !! 0
        initials = [firstInitial] ++ "." ++ [lastInitial] ++ "."

是否可以在main 函数内部调用initials 函数,即使它是在person 函数内部定义的?

【问题讨论】:

  • 您想要达到的结果是什么?即假设输入的名字和姓氏是“John”和“Doe”。输出应该是什么?
  • @senshin 在这种情况下,输出将是“J.D.”。我更新了问题以澄清这一点。

标签: haskell nested-function


【解决方案1】:

您误解了where 的作用:它只是定义范围,这意味着它们只能在它们所附加的项目中使用,在这种情况下,initials 只能在 person 中使用。

换句话说,您正在定义一个函数person :: String -> String -> [String](获取两个字符串并返回它们的列表),该函数的内部实现细节包括一些(未使用的)值initials。它像其他语言中的结构或类,其中initials 是所有persons 都可以访问的某个值。 (无论如何person 只是返回一个字符串列表,而不是一个新类型。)另外,. 不是一个字段访问器,它只是一个方便的函数组合助手。

您似乎想要创建 Person 数据类型,类似于

data Person = Person { firstName :: String, lastName :: String }

这是通过"record syntax" 定义Person

现在,您可以编写一个接受 Person 并返回其首字母的函数:

-- using pattern matching
initials (Person {firstName = f, lastName = l}) =
    [f !! 0] ++ "." ++ [l !! 0] ++ "."

-- or, using the accessors implicitly defined via record syntax
initials p = [firstName p !! 0] ++ "." ++ [lastName p !! 0] ++ "."

这样使用

putStrLn (initials (Person { firstName = "first", lastName = "last" }))

-- or, just using positional arguments (which still work with record syntax)
putStrLn (initials (Person "first" "last"))

【讨论】:

    【解决方案2】:

    initials 不是函数。它只是您在person 的正文中定义的一个变量。如果您只想显示首字母缩写,那很简​​单:

    main =
        putStrLn (initials "John" "Doe")
    
    initials :: String -> String -> String
    initials firstName lastName = 
        [firstInitial] ++ "." ++ [lastInitial] ++ "."
        where
            firstInitial = firstName !! 0
            lastInitial  =  lastName !! 0 
    

    在 GHCi 中:

    *Main> main
    J.D.
    

    或者,在稍微更高的抽象层次上,

    main =
        putStrLn (initials ["John", "Queue", "Public"])
    
    initials :: [String] -> String
    initials (name:names) = [name !! 0] ++ "." ++ initials names
    initials _            = ""
    

    在 GHCi 中:

    *Main> main
    J.Q.P.
    

    我不完全理解您为什么要编写 person 函数 - 它为输入“John”和“Doe”返回“John.Doe”,但我看不出这对打印首字母“J.D.”。

    【讨论】:

      最近更新 更多