Convert an uncurried function to a curried function.
Examples
curry fst 1 21
:: a typeCtrl KGHC 9.10.3 · lts/ghc-9.10.x · 248f8f0 · 2026-10-05
Moduleextra-1.8Haskell2010
Extra functions for working with pairs and triples. Some of these functions are available in the Control.Arrow module, but here are available specialised to pairs. Some operations work on triples.
Convert an uncurried function to a curried function.
curry fst 1 21
Extract the first component of a pair.
Extract the second component of a pair.
uncurry converts a curried function to a function on pairs.
uncurry (+) (1,2)3
uncurry ($) (show, 1)"1"
map (uncurry max) [(1,2), (3,4), (6,8)][2,4,8]
Solo is the canonical lifted 1-tuple, just like Tuple2 is the canonical
lifted 2-tuple (pair) and Tuple3 is the canonical lifted 3-tuple (triple).
The most important feature of Solo is that it is possible to force its
"outside" (usually by pattern matching) without forcing its "inside",
because it is defined as a datatype rather than a newtype. One situation
where this can be useful is when writing a function to extract a value from
a data structure. Suppose you write an implementation of arrays and offer
only this function to index into them:
index :: Array a -> Int -> a
Now imagine that someone wants to extract a value from an array and store it in a lazy-valued finite map/dictionary:
insert "hello" (arr index 12) m
This can actually lead to a space leak. The value is not actually extracted from the array until that value (now buried in a map) is forced. That means the entire array may be kept live by just that value! Often, the solution is to use a strict map, or to force the value before storing it, but for some purposes that's undesirable.
One common solution is to include an indexing function that can produce its
result in an arbitrary Applicative context:
indexA :: Applicative f => Array a -> Int -> f a
When using indexA in a pure context, Solo serves as a handy
Applicative functor to hold the result. You could write a non-leaky
version of the above example thus:
case arr indexA 12 of
Solo a -> insert "hello" a m
While such simple extraction functions are the most common uses for unary tuples, they can also be useful for fine-grained control of strict-spined data structure traversals, and for unifying the implementations of lazy and strict mapping functions.
MkSolo aMonad SoloDefined in ghc-internal-9.1003.0 · GHC.Internal.BaseFunctor SoloDefined in ghc-internal-9.1003.0 · GHC.Internal.BaseMonadFix SoloDefined in ghc-internal-9.1003.0 · GHC.Internal.Control.Monad.FixApplicative SoloDefined in ghc-internal-9.1003.0 · GHC.Internal.BaseFoldable SoloDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableTraversable SoloDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.TraversableMonadZip SoloDefined in base-4.20.2.0 · Control.Monad.ZipFoldable1 SoloDefined in base-4.20.2.0 · Data.Foldable1Eq1 SoloDefined in base-4.20.2.0 · Data.Functor.ClassesOrd1 SoloDefined in base-4.20.2.0 · Data.Functor.ClassesRead1 SoloDefined in base-4.20.2.0 · Data.Functor.ClassesShow1 SoloDefined in base-4.20.2.0 · Data.Functor.ClassesNFData1 SoloDefined in deepseq-1.5.0.0 · Control.DeepSeqGeneric1 SoloDefined in ghc-internal-9.1003.0 · GHC.Internal.GenericsBounded a => Bounded (a)Defined in ghc-internal-9.1003.0 · GHC.Internal.EnumEnum a => Enum (a)Defined in ghc-internal-9.1003.0 · GHC.Internal.EnumEq a => Eq (a)Defined in ghc-prim-0.12.0 · GHC.ClassesData a => Data (a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.DataOrd a => Ord (a)Defined in ghc-prim-0.12.0 · GHC.ClassesRead a => Read (a)Defined in ghc-internal-9.1003.0 · GHC.Internal.ReadShow a => Show (a)Defined in ghc-internal-9.1003.0 · GHC.Internal.ShowIx a => Ix (a)Defined in ghc-internal-9.1003.0 · GHC.Internal.IxGeneric (a)Defined in ghc-internal-9.1003.0 · GHC.Internal.GenericsSemigroup a => Semigroup (a)Defined in ghc-internal-9.1003.0 · GHC.Internal.BaseMonoid a => Monoid (a)Defined in ghc-internal-9.1003.0 · GHC.Internal.BaseNFData a => NFData (a)Defined in deepseq-1.5.0.0 · Control.DeepSeqtype Rep (a) = D1 ('MetaData "Solo"
"GHC.Tuple"
"ghc-prim"
'False) (C1 ('MetaCons "MkSolo"
'PrefixI 'False) (S1 ('MetaSel 'Nothing 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 a)))Defined in ghc-internal-9.1003.0 · GHC.Internal.Genericstype Rep1 Solo = D1 ('MetaData "Solo"
"GHC.Tuple"
"ghc-prim"
'False) (C1 ('MetaCons "MkSolo"
'PrefixI 'False) (S1 ('MetaSel 'Nothing 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) Par1))Defined in ghc-internal-9.1003.0 · GHC.Internal.GenericsDeprecated. The Solo constructor has been renamed to MkSolo to avoid punning.
Swap the components of a pair.
Extract the value from a Solo. Very often, values should be extracted
directly using pattern matching, to control just what gets evaluated when.
getSolo is for convenience in situations where that is not the case:
When the result is passed to a strict function, it makes no difference whether the pattern matching is done on the "outside" or on the "inside":
Data.Set.insert (getSolo sol) set === case sol of Solo v -> Data.Set.insert v set
A traversal may be performed in Solo in order to control evaluation
internally, while using getSolo to extract the final result. A strict
mapping function, for example, could be defined
map' :: Traversable t => (a -> b) -> t a -> t b
map' f = getSolo . traverse ((Solo $!) . f)
Arrow functionsUpdate the first component of a pair.
first succ (1,"test") == (2,"test")Update the second component of a pair.
second reverse (1,"test") == (1,"tset")Given two functions, apply one to the first component and one to the second. A specialised version of ***.
(succ *** reverse) (1,"test") == (2,"tset")Given two functions, apply both to a single argument to form a pair. A specialised version of &&&.
(succ &&& pred) 1 == (2,0)Duplicate a single value into a pair.
dupe 12 == (12, 12)Apply a single function to both components of a pair.
both succ (1,2) == (2,3)Update the first component of a pair.
firstM (\x -> [x-1, x+1]) (1,"test") == [(0,"test"),(2,"test")]Update the second component of a pair.
secondM (\x -> [reverse x, x]) (1,"test") == [(1,"tset"),(1,"test")]Extract the fst of a triple.
Extract the snd of a triple.
Extract the final element of a triple.
Update the first component of a triple.
first3 succ (1,1,1) == (2,1,1)Update the second component of a triple.
second3 succ (1,1,1) == (1,2,1)Update the third component of a triple.
third3 succ (1,1,1) == (1,1,2)Converts an uncurried function to a curried function.
Converts a curried function to a function on a triple.