Here are a few simple functions:
f1 :: () -> ()
f1 () = ()
f2 :: a -> a
f2 a = a
f3 :: a -> (a, a)
f3 a = (a, a)
f4 :: (a, b) -> a
f4 (a, b) = a
All of f1, f2, and f3 are able to accept () as an input. On the other hand, of course, f4 can't accept (); f4 () is a type error.
Is it possible to type-theoretically characterize what f1, f2, and f3 have in common? Specifically, is it possible to define an acceptsUnit function, such that acceptsUnit f1, acceptsUnit f2, and acceptsUnit f3 are well-typed, but acceptsUnit f4 is a type error -- and which has no other effect?
The following does part of the job, but monomorphizes its input (in Haskell, and I gather in Hindley-Milner), and hence has an effect beyond simply asserting that its input can accept ():
acceptsUnit :: (() -> a) -> (() -> a)
acceptsUnit = id
-- acceptsUnit f4 ~> error
-- acceptsUnit f3 'a' ~> error ☹️
The same monomorphizing, of course, happens in the following. In this case, the annotated type of acceptsUnit' is its principal type.
acceptsUnit' :: (() -> a) -> (() -> a)
acceptsUnit' f = let x = f () in f