问题
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 person
s 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