1

How can I define a function that takes no arguments?

data Address
   = Address
   {
       city :: String,
       street :: String
   }
   deriving ( Show )

-- mkIncompleteAddress :: () -> Address
-- mkIncompleteAddress = Address "NYC" "<TBD>"

mkIncompleteAddress :: Address
mkIncompleteAddress = Address "NYC" "<TBD>"

The closest I can get is a constant (?) global variable (?) When I remove the comments I get:

Main.hs:10:23: error:
    • Couldn't match expected type ‘() -> Address’
                  with actual type ‘Address’
    • Possible cause: ‘Address’ is applied to too many arguments
      In the expression: Address "NYC" "<TBD>"
      In an equation for ‘mkIncompleteAddress’:
          mkIncompleteAddress = Address "NYC" "<TBD>"
2
  • 2
    What do you mean by "function that takes no arguments", if not what you have here? And, once you've said what you mean, why do you want that? Commented Sep 24, 2022 at 4:00
  • @DanielWagner I have Addresses that are either partial or complete. At some later phase, the partial addresses will be completed. I thought I'd "allocate" a partial address and "complete" it later. I guess my thinking was "too-cpp-like" as I now see that all these "allocated address" are essentially just a single, constant address Commented Sep 24, 2022 at 7:20

1 Answer 1

3

mkIncompleteAddress :: Address is a function which takes no arguments. In Haskell, that’s more or less the same thing as a global constant, since non-IO functions don’t have side-effects and values are lazily evaluated.

On the other hand, it’s still entirely possible to write a function mkIncompleteAddress :: () -> Address, like so:

mkIncompleteAddress :: () -> Address
mkIncompleteAddress x = Address "NYC" "<TBD>"

Or, you can be really explicit and pattern-match on the input:

mkIncompleteAddress :: () -> Address
mkIncompleteAddress () = Address "NYC" "<TBD>"

Syntactically, this looks a bit like a function with no arguments, but it isn’t: it’s a function which requires one argument, where this argument happens to have () as its only value.


However, I would invite you to reconsider your approach here. Address "NYC" "<TBD>" is, quite obviously, invalid as an address, and using such values in your program just makes mistakes easier to make. I’d recommend doing something like this instead:

mkIncompleteAddress :: String -> Address
mkIncompleteAddress street = Address "NYC" street

Or even simpler, taking advantage of currying:

mkIncompleteAddress :: String -> Address
mkIncompleteAddress = Address "NYC"
Sign up to request clarification or add additional context in comments.

3 Comments

To expand on your first point: precisely speaking, Haskell functions are types that go … -> …, and they all take exactly 1 parameter; yet in practice we also often refer to a function as taking 2 or more parameters, as if it weren’t curried. So, even though it is a common misconception that a value is a 0-parameter function, I don’t think there’s really any harm in it either, as an illustration to help learn the language.
Thanks ! I'll consider that idea. The only thing that bothers me is that I have some complete addresses and some partial addresses being handled by the same functions - so using your suggestion, these 2 addresses kinds will have different types, right?
@OrenIshShalom If you genuinely do need to handle partial addresses so often, I’d suggest reflecting that directly in the type: something like data Address = Address { city :: String, street :: Maybe String }, perhaps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.