0

Is it reasonable to omit explicit function signatures when they are trivial?

data Token = Token String Int deriving ( Show )
data Person = Person Token deriving ( Show )

-- Is it ok to omit explicit signature ?
-- name_getter :: Person -> String
name_getter (Person (Token name _)) = name

Should I keep them for readability?

OrenIshShalom
  • 5,974
  • 9
  • 37
  • 87

2 Answers2

3

If you want readability, you might want to consider named members. This has two advantages:

  1. It is clear what each field is for
  2. Haskell automatically derives access functions, function name is the same as the field name

Then the code looks like this:

data Token = Token {name:: String, age::Int} deriving ( Show )
data Person = Person {token::Token} deriving ( Show )

main = do
   let person = Person $ Token "Joe" 39 
   print $ name $ token person 

[EDIT]

As to whether, in general, it is worth putting in signatures for very simple functions - this is very subjective.

Not putting in signatures saves typing, and can reduce the length of simple functions on the screen. Haskell can derive the signatures automatically.

If you are using Visual Studio Code and HLS, HLS will suggest a signature, and you can accept what it offers. The way HLS is set up on my computer, if there isn't a signature provided it will offer one, and so there is no saving on function length.

I would personally include function signatures because that's my style, such as it is. If the getters are stacked up one after the other with comments as to what it does, you might decide to not do so.

Francis King
  • 1,652
  • 1
  • 7
  • 14
  • See [my other related question](https://stackoverflow.com/questions/73871836/haskell-use-of-getters-instead-of-pattern-match), this is legacy code I cannot touch, so I'm stuck with a non-record format – OrenIshShalom Sep 28 '22 at 07:04
  • @OrenIshShalom. I've expanded my answer. – Francis King Sep 28 '22 at 08:24
3

You can "fix" legacy code using a pattern synonym to add record syntax to a legacy type.

{-# LANGUAGE PatternSynonyms #-}

-- legacy code, we can not touch this

data Token = Token String Int deriving ( Show )
data Person = Person Token deriving ( Show )

-- new code to add record fields to the legacy type

pattern P :: String -> Int -> Person
pattern P { name, tok } = Person (Token name tok)

-- tests

-- use standard syntax to construct a new value
person1 :: Person
person1 = P "aaa" 42

-- use record syntax to construct a new value
person2 :: Person
person2 = P { name = "bbb" , tok = 43 }

-- use the field getter
usePerson1 :: Person -> String
usePerson1 p = "The name is " ++ name p

-- use pattern matching    
usePerson2 :: Person -> String
usePerson2 P{name = n} = "The name is " ++ n
chi
  • 111,837
  • 3
  • 133
  • 218