fmap 如何与数据构造函数一起使用?
How can fmap be used with a data constructor?
我正在尝试理解一些 haskell 代码。
这是有道理的。
Prelude> fmap (+1) (Just 1)
Just 2
这也有道理。
Prelude> (fmap.fmap) (+1) (Just [1])
Just [2]
但我不明白这是怎么回事。
Prelude> (fmap.fmap) (+1) Just 1
Just 2
我试过把零件拼出来。在我看来,这就是正在发生的事情。
(fmap (fmap (+1)) Just) 1
我尝试输入子表达式。
这是有道理的。
Prelude> :t fmap (+1)
fmap (+1) :: (Functor f, Num b) => f b -> f b
这还是有道理的。
Prelude> :t fmap (fmap (+1))
fmap (fmap (+1)) :: (Functor f, Functor f1, Num b) =>
f (f1 b) -> f (f1 b)
但是我不明白这个。
Prelude> :t fmap (fmap (+1)) Just
fmap (fmap (+1)) Just :: Num b => b -> Maybe b
类型的函数是如何实现的
(Functor f, Functor f1, Num b) => f (f1 b) -> f (f1 b)
应用 Just
后,其类型为:
a -> Maybe a
这种类型的结果?
Num b => b -> Maybe b
问题confused about function as instance of Functor in haskell可能与此有关,但我仍然很困惑。
f
解析为仿函数 (->) a
,f1
解析为 Maybe
,因为
Just :: (->) a (Maybe a)
因此,如果我们使用上述绑定编写 fmap (fmap (+1))
的类型,我们将得到:
fmap (fmap (+1)) :: Num b => (->) a (Maybe b) -> (->) a (Maybe b)
重写 (->)
作为中缀构造函数我们得到:
fmap (fmap (+1)) :: Num b => (a -> Maybe b) -> (a -> Maybe b)
现在我们将它应用到 Just :: a -> Maybe a
所以我们得到
fmap (fmap (+1)) Just :: Num a => a -> Maybe a
您写 Just 1
而不是 (Just 1)
因此,这是两个独立的参数。我们现在可以用更规范的形式重写它,例如:
(fmap . fmap) (+1) Just 1
-> (\x -> fmap (fmap x)) (+1) Just 1
-> ((fmap (fmap (+1)) Just) 1
现在我们可以分析类型了:
fmap<i>1</i> :: Functor f => (a -> b) -> f a -> f b
fmap<i>2</i> :: Functor g => (c -> d) -> g c -> g d
(+1) :: Num h => h -> h
Just :: i -> Maybe i
1 :: Num j => j
其中fmap<i>i</i>
是第i-thfmap
表达式(如果我们读取它 left-to-right)。如果我们知道执行一些分析,我们会看到因为我们使用 fmap (+1)
,所以我们知道 c ~ d ~ h
:
fmap<i>1</i> :: Functor f => (a -> b) -> f a -> f b
fmap<i>2</i> :: Functor g => (h -> h) -> g h -> g h
(+1) :: Num h => h -> h
Just :: i -> Maybe i
1 :: Num j => j
然后我们看到第一个 fmap
(fmap<i>1</i>
) 被调用 fmap (+1) :: Functor g => g h -> g h
作为第一个参数,Just :: i -> Maybe i
作为第二个参数。因此,如果我们进一步执行类型分析,我们得到:(a -> b) ~ g h -> g h
,所以 a ~ b ~ g h
,并且我们知道 f (g h) ~ i -> Maybe i
,所以这意味着 f (g h) ~ (->) i (Maybe i)
所以 f ~ (->) i
和 g ~ Maybe
, h ~ i
, 此外 i ~ j
:
fmap<i>1</i> :: (Maybe i -> Maybe i) -> (->) i (Maybe i) -> (->) i Maybe i
fmap<i>2</i> :: (i -> i) -> Maybe i -> Maybe i
(+1) :: Num h => i -> i
Just :: i -> Maybe i
1 :: Num i => i
现在这里的一个关键方面是 (->) r
也是一个函子,确实在 base-4.10.1.0
source code 中我们看到:
instance Functor ((->) r) where
fmap = (.)
我们可以在这里将函数视为函子,如果我们执行 fmap
我们 "post process" 结果。所以这意味着 在 我们应用 Just
之后,我们应用 fmap (+1)
到那个结果。所以第一个 fmap
相当于 (.)
而第二个 fmap
超过 Maybe
,结果我们得到:
((fmap (fmap (+1)) Just) 1
-> (((.) (fmap (+1)) Just) 1
-> ((\x -> (fmap (+1) (Just x)) 1
-> fmap (+1) (Just 1)
-> Just 2
所以简而言之,我们使用 (fmap (+1))
作为 post 处理 步骤,在 我们应用 Just
到 1
.
我正在尝试理解一些 haskell 代码。
这是有道理的。
Prelude> fmap (+1) (Just 1)
Just 2
这也有道理。
Prelude> (fmap.fmap) (+1) (Just [1])
Just [2]
但我不明白这是怎么回事。
Prelude> (fmap.fmap) (+1) Just 1
Just 2
我试过把零件拼出来。在我看来,这就是正在发生的事情。
(fmap (fmap (+1)) Just) 1
我尝试输入子表达式。
这是有道理的。
Prelude> :t fmap (+1)
fmap (+1) :: (Functor f, Num b) => f b -> f b
这还是有道理的。
Prelude> :t fmap (fmap (+1))
fmap (fmap (+1)) :: (Functor f, Functor f1, Num b) =>
f (f1 b) -> f (f1 b)
但是我不明白这个。
Prelude> :t fmap (fmap (+1)) Just
fmap (fmap (+1)) Just :: Num b => b -> Maybe b
类型的函数是如何实现的
(Functor f, Functor f1, Num b) => f (f1 b) -> f (f1 b)
应用 Just
后,其类型为:
a -> Maybe a
这种类型的结果?
Num b => b -> Maybe b
问题confused about function as instance of Functor in haskell可能与此有关,但我仍然很困惑。
f
解析为仿函数 (->) a
,f1
解析为 Maybe
,因为
Just :: (->) a (Maybe a)
因此,如果我们使用上述绑定编写 fmap (fmap (+1))
的类型,我们将得到:
fmap (fmap (+1)) :: Num b => (->) a (Maybe b) -> (->) a (Maybe b)
重写 (->)
作为中缀构造函数我们得到:
fmap (fmap (+1)) :: Num b => (a -> Maybe b) -> (a -> Maybe b)
现在我们将它应用到 Just :: a -> Maybe a
所以我们得到
fmap (fmap (+1)) Just :: Num a => a -> Maybe a
您写 Just 1
而不是 (Just 1)
因此,这是两个独立的参数。我们现在可以用更规范的形式重写它,例如:
(fmap . fmap) (+1) Just 1
-> (\x -> fmap (fmap x)) (+1) Just 1
-> ((fmap (fmap (+1)) Just) 1
现在我们可以分析类型了:
fmap<i>1</i> :: Functor f => (a -> b) -> f a -> f b
fmap<i>2</i> :: Functor g => (c -> d) -> g c -> g d
(+1) :: Num h => h -> h
Just :: i -> Maybe i
1 :: Num j => j
其中fmap<i>i</i>
是第i-thfmap
表达式(如果我们读取它 left-to-right)。如果我们知道执行一些分析,我们会看到因为我们使用 fmap (+1)
,所以我们知道 c ~ d ~ h
:
fmap<i>1</i> :: Functor f => (a -> b) -> f a -> f b
fmap<i>2</i> :: Functor g => (h -> h) -> g h -> g h
(+1) :: Num h => h -> h
Just :: i -> Maybe i
1 :: Num j => j
然后我们看到第一个 fmap
(fmap<i>1</i>
) 被调用 fmap (+1) :: Functor g => g h -> g h
作为第一个参数,Just :: i -> Maybe i
作为第二个参数。因此,如果我们进一步执行类型分析,我们得到:(a -> b) ~ g h -> g h
,所以 a ~ b ~ g h
,并且我们知道 f (g h) ~ i -> Maybe i
,所以这意味着 f (g h) ~ (->) i (Maybe i)
所以 f ~ (->) i
和 g ~ Maybe
, h ~ i
, 此外 i ~ j
:
fmap<i>1</i> :: (Maybe i -> Maybe i) -> (->) i (Maybe i) -> (->) i Maybe i
fmap<i>2</i> :: (i -> i) -> Maybe i -> Maybe i
(+1) :: Num h => i -> i
Just :: i -> Maybe i
1 :: Num i => i
现在这里的一个关键方面是 (->) r
也是一个函子,确实在 base-4.10.1.0
source code 中我们看到:
instance Functor ((->) r) where fmap = (.)
我们可以在这里将函数视为函子,如果我们执行 fmap
我们 "post process" 结果。所以这意味着 在 我们应用 Just
之后,我们应用 fmap (+1)
到那个结果。所以第一个 fmap
相当于 (.)
而第二个 fmap
超过 Maybe
,结果我们得到:
((fmap (fmap (+1)) Just) 1
-> (((.) (fmap (+1)) Just) 1
-> ((\x -> (fmap (+1) (Just x)) 1
-> fmap (+1) (Just 1)
-> Just 2
所以简而言之,我们使用 (fmap (+1))
作为 post 处理 步骤,在 我们应用 Just
到 1
.