为了明确起见,这里有一个简单的函数对象:
这使得我们能够在“盒子内”运作:
当然,我不能将Width或Height作为Functor的实例,因为它们的类型不是
此外,由于每次创建新的newtype都需要重复此操作,因此创建n个这样的函数并不令人满意。
我如何将一个作用于Ints的函数扩展为作用于Widths的函数?
data Box a = Box a deriving (Show)
instance Functor Box where
fmap f (Box x) = Box (f x)
这使得我们能够在“盒子内”运作:
> fmap succ (Box 1)
Box 2
我如何通过 newtype 实现相同的语法上的方便性? 假设我有以下代码:
newtype Width = Width { unWidth :: Int } deriving (Show)
newtype Height = Height { unHeight :: Int } deriving (Show)
这有点笨重:
> Width $ succ $ unWidth (Width 100)
Width {unWidth = 101}
这会很不错:
> fmap succ (Width 100) -- impossible?
Width {unWidth = 101}
当然,我不能将Width或Height作为Functor的实例,因为它们的类型不是
* -> *
。虽然,从语法上看它们与Box没有任何区别,因此似乎应该可以在不进行手动包装和解包的情况下操作其底层值。此外,由于每次创建新的newtype都需要重复此操作,因此创建n个这样的函数并不令人满意。
fmapWidth :: (Int -> Int) -> Width -> Width
fmapHeight :: (Int -> Int) -> Height -> Height
我如何将一个作用于Ints的函数扩展为作用于Widths的函数?
over
:给定一个称为unWidth
的字段的镜头,over unWidth
可以实现你想要的功能(即它允许你使用单态函子)。 - duplode