What is the special status of a 2-tuple?

Reading Real World Haskell and Typeclassopedia I am under the impression that 2-tuples (a,b)

can have very special roles in Haskell.

The first use I came across is lookup

where we use a list of 2 tuples as a dictionary.

Then I also ran into what ((,) e)

is an instance of a functor (but not another n-tuple), which makes sense in the example above, for example (key,value)

.

Now the very last case that I really want to ask about is in chapter 4.3 of Typeclassopedia. It says what ((,) a)

is an instance Applicative

if it a

is a monoid. When do you actually use it? What are the applications in which you are using the instance Applicative

(a,b)

?

+3


source to share


1 answer


Nothing prevents us from writing an instance for triples or arbitrary n-tuples:

instance Functor ((,,) a b) where
  fmap f (x,y,z) = (x,y,f z)

instance (Monoid a, Monoid b) => Applicative ((,,) a b) where
  pure z              = (mempty,        mempty,          z)
  (a,b,f) <*> (x,y,z) = (a `mappend` x, b `mappend` y, f z)

      

Pairs are not special, so in the sense that you can implement an instance for any n-tuple. But since these cases must be written somewhere, he asks the question how far should we go. For example, Monoid

instances are defined with up to 5 tuples. Of course, you can write them for 10 tuples, but we're just copying the boiler room code at this point.

That being said, couples are special because their collection provides a natural way to describe a relationship. One example is a dictionary that links a term and its definition:

dictionary :: [(String, String)]
dictionary =
  [("cat", "animal that likes strings; not Strings, though")
  ,("dog", "animal that likes you; yes you")
  ,("foo", "a strange word used by programmers in examples")
  ]

      

Another way to show that the relation (if the first parts of all pairs were unique) would be

partialDictionaryEntry :: String -> String

      

if we limit the input area "cat"

, "dog"

and "foo"

, or



dictionaryEntry :: String -> Maybe String

      

which is \s -> lookup s dictionary

. And with pairs, you can simulate any other n-tuple:

(a,b,z)   = ((a,b),z)
(a,b,c,z) = ((a,b,c),z) = (((a,b),c),z)

      

In this sense, they are the smallest container that provides this functionality. We can construct all other types of tuples from pairs. Hell, in theory we don't even need to write our instance Applicative ((,,) a b)

as it is already provided for (,) (a,b)

because of the instance Monoid

.

As the saying goes, why does it even have a copy Applicative

? This is the simplest implementation Writer

:

log :: (Show a) => a -> (String, a)
log x = (show x ++ "\n", x)

fivePlusThree = (+) <$> log 3 <*> log 5

main = do
  let (logs, result) = fivePlusThree
  putStrLn logs
  print result

      

3
5

8

      

This provides an easy way to add additional information to functions or values, although you are likely to use a method Writer

and its method Writer

as they are nicer to use and provide a rigorous option.

+5


source







All Articles