Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell type signature with composite/multi-param type constructors

I've discovered these kinds of type signatures:

x :: a b -> Int
x f = 3

y :: a b c -> Int
y f = 3

z :: a b c d -> Int
z f = 3

> x [1] -- 3
> y (1, 2) -- 3
> z (1, 2, 3) -- 3

Basically:

  1. x only accepts a value inhabiting a type constructor with 1 parameter or more.
  2. y only accepts a value inhabiting a type constructor with 2 parameters or more.
  3. z only accepts a value inhabiting a type constructor with 3 parameters or more.

They are valid, but I'm not sure what they mean nor what they could be used for.

They seem related to polytypic notions or polymorphism over type constructors, but enforce an invariant based on many parameters the type constructor accepts.

like image 317
CMCDragonkai Avatar asked Feb 10 '23 14:02

CMCDragonkai


1 Answers

Without further constraints, such types are useless – there's nothing you could really do with them, expect pass them right on. But that's actually the same situation with a signature a -> Int: if nothing is known about a, there's nothing you can do with it either!

However, like with e.g. toInteger :: Integral a => a -> Integer, adding constraints to the arguments allows you to do stuff. For instance,

import Data.Foldable
import Prelude hiding (foldr)

x' :: (Foldable a, Integral b) => a b -> Integer
x' = foldr ((+) . toInteger) 0

Rather more often than not, when you have a type of the form a b ... n o p q, then a b ... p is at least an instance of the Functor class, often also Applicative and Monad; sometimes Foldable, Traversable, or Comonad; sometimes a b ... o will be Arrow... These constraints allow you to do quite a lot with the composite types, without knowing what particular type constructors you're dealing with.

like image 119
leftaroundabout Avatar answered May 10 '23 20:05

leftaroundabout