Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Applying Function Passed as Argument to Different Types in Haskell

Is there any way to apply a function passed as an argument to two different types? As a contrived example, I can create a (Maybe Int, Maybe Bool) with the expression (Just 3, Just True), but if I try to make this behaviour more generic with the function

generic :: (a -> Maybe a) -> (Maybe Int, Maybe Bool)
generic f = (f 3, f True)

so that I might be able to do something like generic Just, the compiler complains because the type variable a is constant.

The use case of this is applying a generic function to a tree structure where each node is parametrized by a type.

like image 824
igorbark Avatar asked Feb 05 '16 03:02

igorbark


1 Answers

This can be achieved using rank-2 polymorphism as follows:

{-# LANGUAGE Rank2Types #-}
generic :: (forall a. a -> Maybe a) -> (Maybe Int, Maybe Bool)
generic f = (f 3, f True)

Often you will need some typeclass restriction (not because the implementation of generic demands it, but because the caller cannot pass an argument that works for all types), e.g.

genericNum :: (forall a. Num a => a -> a) -> (Int, Integer)
genericNum f = (f 3, f 9)
like image 158
Daniel Wagner Avatar answered Sep 27 '22 20:09

Daniel Wagner