Making (a, a) a Functor

痴心易碎 提交于 2019-11-28 21:19:11

As others have stated, there's no way to do this without resorting to newtypes or data declarations. However, have you looked at Control.Arrow? Many of those functions are very useful with tuples, for example:

vmap :: (a -> b) -> (a,a) -> (b,b)
vmap f = f *** f

You can declare

instance Functor ((,) a) where
  ...

However that doesn't constrain the first element of your pair, and fmap would only act on the second element.

The issue is that a tuple doesn't enforce a relationship between the types of the two elements.

If you don't want a newtype decorator you can make your own fresh type:

data Pair a = P a a

instance Functor Pair where
  ...

which will be easier to work with than a newtype around a tuple.

With singletons you can define a Functor type class for defunctionalized symbols (Type ~> Type instead of Type -> Type)

{-# Language ExplicitNamespaces, TypeApplications, TypeOperators, KindSignatures, ScopedTypeVariables, DataKinds, TypeInType, TypeFamilies, AllowAmbiguousTypes, InstanceSigs #-}

import Data.Kind (Type)
import Data.Singletons (type (~>), Apply)

class Functor' (f :: Type ~> Type) where
  fmap' :: (a -> a') -> (Apply f a -> Apply f a')

data Dup :: Type ~> Type

type instance Dup `Apply` a = (a, a)

instance Functor' Dup where
  fmap' :: (a -> a') -> ((a, a) -> (a', a'))
  fmap' f (a1, a2) = (f a1, f a2)

This gives you a Prelude.Functor instance automatically

newtype f $ a = App (Apply f a)

instance Functor' f => Functor (($) f) where
  fmap :: (a -> a') -> (f $ a -> f $ a')
  fmap f (App fa) = App (fmap' @f f fa) 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!