如何为包含函数的新类型构建 fmap

How to construct fmap for a newtype that houses functions

假设我想定义一个包含函数的新类型:

newtype Test m a = Test(m -> (a, m))

这可以用来容纳某种状态。

现在假设我想为这个新类型实现 fmap。

instance Functor (Test m) where
    --fmap :: (a -> b) -> Test m a -> Test m a -> b
    fmap f (Test f1) (Test f2) = ?

由于 newtype house 的功能,因此无法使用模式匹配将 f1 和 f2 分开。

例如,我最初认为也许我可以将 f2 的输入值传递给调用 f1 以生成 (a, m) 元组,但我认为您不能那样做。

tup = f1 (get input of f2)

是否有人能够向我提供我在处理这种情况时缺少的概念,或者这是不可能的?

谢谢

更新

非常感谢 Redu 和 Willem Van Onsem。

看来我对如何使用组合运算符 (.) 缺乏了解。

基本上这里的关键是用(.)抓取元组的第一个元素,然后做一堆偏函数定义,进入fmap需要的状态。这是我不使用库函数的 fmap 实现。故意冗长以帮助理解。

alterParamStateHelper :: (a -> b) -> (m -> a) -> m -> (b, m)
alterParamStateHelper f1 f2 m = (b, m)
  where 
    a = f2 e
    b = f1 a

alterParamState :: (a -> b) -> (m -> (a, m)) -> (m -> (b, m))
alterParamState f1 f2 = alterParamStateHelper f1 h1
  where
    h1 = fst . f2--m -> a

instance Functor (Test m) where
  -- fmap :: (a -> b) -> Test m a -> Test m b
  fmap f1 (Test f2) = Test (alterParamState f1 f2)

Since the newtype houses functions there's no way to use pattern matching to break f1 and f2 apart.

您的 fmap 签名有问题。 fmap 具有签名 fmap :: Functor f => (a -> b) -> f a -> f b,因此如果 f ~ Test m,则签名为 fmap :: (a -> b) -> Test m a -> Test m b

因此,我们可以在这里定义一个 fmap,其中我们 "post-process" 函数的结果。因此,我们构造一个新函数,它将使用旧函数构造一个二元组 (a, m),然后在第一项上调用 f,这样我们构造一个元组 (b, m):

import Control.Arrow(<b>first</b>)

instance Functor (Test m) where
    fmap f (Test g) = Test (<b>first f . g</b>)