将fmap类型声明与其使用方式进行比较

时间:2016-05-02 08:22:34

标签: haskell

我跑了:t fmap (*) (Just 5)并得到了

fmap (*) (Just 5) :: Num a => Maybe (a -> a)

fmap的类型声明说

fmap :: Functor f => (a -> b) -> f a -> f b

我认为(*)被视为(a -> (a -> a))并且对应于fmap类型声明的(a -> b)部分,我是否正确?如果(a -> a)部分对应b,为什么我不能执行以下操作?让b代表lambda函数吗?

foo :: a -> b
foo x = (\y -> y + 3)

2 个答案:

答案 0 :(得分:5)

您的签名中隐含forall

foo :: forall a b. a -> b

这意味着您的功能必须适用于 任何 ab。让我们来看看你的功能:

foo x = (\y -> y + 3)

由于x=的右侧没有受到限制,因此它符合要求:它可以是任何类型。但是,您的右侧有以下类型:

ghci> :t (\y -> y + 3)
Num k => k -> k

请记住,您的原始函数表示b的选择可以是任意的。但是,您的函数正在将返回类型限制为b ~ Num k => k -> k。你必须使用

foo :: Num b => a -> b -> b

顺便说一句,foo的类型已经表明你不会使用第一个参数,因为没有办法以一般的方式组合不同类型的两个值。实际上,可以证明某些foo const bar bar :: Num b => b -> bforall a b. a -> b

锻炼

  • 尝试考虑类型为function tytPreGetBool(pre) { return localStorage.getItem(pre) == 'true' ? true : false; } 的函数。

答案 1 :(得分:1)

在您的初始示例中,由于aNum5被限制为(*)的实例。

:type 5
   5 :: Num a => a

:type (*)
   (*) :: Num a => a -> a -> a

{J} (a->a)与[{1}}类型b统一是正确的。

fmap

因此:

:type (\y -> y + 3)
    (\y -> y + 3) :: Num a => a -> a

正如Willem Van Onsem所说,:type foo foo :: Num a => t -> a -> a 意味着"任何你喜欢的类型",而不是"任何符合我无法提及的无形约束的类型"。