dino
dino

Reputation: 1133

When should TypeApplications be preferred over simple :: signatures or ScopedTypeVariables?

Considering this simple example of ambiguous type inference:

#! /usr/bin/env stack
{- stack runghc -}

{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

main :: IO ()
main = do
  -- This will fail to compile without additional type info
  -- let w = read "22"
  -- print w
  
  -- My go-to for this is type signatures in the expressions
  let x = read "33" :: Integer
  print x 
  
  -- Another possibility is ScopedtypeVariables
  let y :: Integer = read "44"
  print y
  
  -- How does TypeApplications differ from the code above? When should this be chosen instead?
  let z = read @Integer "55"
  print z

My question is, in cases like this, is there an advantage to using TypeApplications?

Upvotes: 3

Views: 176

Answers (1)

Daniel Wagner
Daniel Wagner

Reputation: 152927

In almost all cases, it is an aesthetic choice only. I make the following additional comments for your consideration:

  • In all cases, if a thing typechecks with some collection of type signatures, there is a corresponding collection of type applications that also causes that term to typecheck (and with the same choices of instance dictionaries, etc.).

  • In cases where either a signature or an application can be used, the code produced by GHC will be identical.

  • Some ambiguous types cannot be resolved via signatures, and type applications must be used. For example, foo :: (Monoid a, Monoid b) => b cannot be given a type signature that determines a. (This bullet motivates the "almost" in the first sentence of this answer. No other bullet motivates the "almost".)

  • Type applications are frequently syntactically lighter than type signatures. For example, when the type is long, or a type variable is mentioned several times. Some comparisons:

      showsPrec :: Int -> Bool -> String -> String
      showsPrec @Bool
    
      sortOn :: Ord b => (Int -> b) -> [Int] -> [Int]
      sortOn @Int
    

    Sometimes it is possible to shuffle the type signature around to a different subterm so that you need only give a short signature with little repetition. But then again... sometimes not.

  • Sometimes, the signature or application is intended to convey some information to the reader or encourage a certain way of thinking about a piece of code (i.e. is not strictly for compiler consumption). If part of that information involves attaching the annotation in a specific code location, your options may be somewhat constrained.

Upvotes: 8

Related Questions