问题
I have defined a function called initials inside a function called person, but I can't figure out how to call initials outside of person:
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] ++ "."
Is it possible to invoke the initials function inside the main function, even though it is defined inside the person function?
回答1:
You're misunderstanding what where does: it just scopes definitions, meaning they can only be used in the item they are attached to, in this case, initials can only be used in person.
In other words, you are defining a function person :: String -> String -> [String] (taking two strings and returning a list of them), where the internal implementation details of this function include some (unused) value called initials. It is not like a struct or class in other languages, where initials is some value that all persons can access. (And anyway person is just returning a list of strings, not a new type.) Also, . is not a field accessor, it is just a convenient helper for function composition.
It seems like you might be wanting to make a Person data type, something like
data Person = Person { firstName :: String, lastName :: String }
This is defining Person via "record syntax".
Now, you can write a function that takes a Person and returns their initials:
-- 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] ++ "."
This is used like
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 isn't a function. It's just a variable you've defined in the body of person. If you just want to display the initials, that's straightforward:
main =
putStrLn (initials "John" "Doe")
initials :: String -> String -> String
initials firstName lastName =
[firstInitial] ++ "." ++ [lastInitial] ++ "."
where
firstInitial = firstName !! 0
lastInitial = lastName !! 0
In GHCi:
*Main> main
J.D.
Or, at a slightly higher level of abstraction,
main =
putStrLn (initials ["John", "Queue", "Public"])
initials :: [String] -> String
initials (name:names) = [name !! 0] ++ "." ++ initials names
initials _ = ""
In GHCi:
*Main> main
J.Q.P.
I don't fully understand why you've written the person function - it returns "John.Doe" for inputs "John" and "Doe", but I don't see how that is useful for printing the initials "J.D.".
来源:https://stackoverflow.com/questions/24235757/invoking-nested-functions-in-haskell