如何为包含函数的新类型构建 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>)
假设我想定义一个包含函数的新类型:
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
andf2
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>)