vik*_*ata 3 haskell function functor difference
在Haskell中,当编写函数时,它意味着我们将某些东西(输入)映射到另一个东西(输出).我试过LYAH来理解Functor的定义:看起来像普通的Functor一样.
很困惑,需要你的建议.谢谢.
Fre*_*abe 12
首先,在Haskell中"一切都是函数"并不是真的.很多东西都不是功能,比如4.或者字符串"vik santata".
在Haskell中,函数是将某些输入映射到输出的东西.函数是一个值,您可以将其应用于某个其他值以获取结果.如果一个值->在其类型中具有a ,则很可能它可能是一个函数(但是这个经验法则存在无限多个例外;-)).
以下是一些函数示例(引用GHCI会话):
?: :t fst
fst :: (a, b) -> a
?: :t even
even :: Integral a => a -> Bool
Run Code Online (Sandbox Code Playgroud)
以下是一些不是函数的例子:
(多态)值a,如果类型是Num类的成员(例如,Int它将是有效类型),则可以采用任何类型.从数字的使用方式推断出确切的值.
请注意,此类型包含=>在内,这与完全不同->.它表示"类约束".
?: :t 5
5 :: Num a => a
Run Code Online (Sandbox Code Playgroud)功能列表.请注意,它有一个->类型,但它不是顶级类型的构造函数(顶层类型是[],即"列表"):
?: :t [fst, snd]
[fst, snd] :: [(a, a) -> a]
Run Code Online (Sandbox Code Playgroud)函数不是可以应用于值的东西.函数类型的值可以与fmap函数一起使用(并由函数返回)(假设fmap函数符合某些规则,通常称为"法则").您可以找到Functor使用GHCI 的基本类型列表:
?: :i Functor
[...]
instance Functor (Either a) -- Defined in ‘Data.Either’
instance Functor [] -- Defined in ‘GHC.Base’
instance Functor Maybe -- Defined in ‘GHC.Base’
[...]
Run Code Online (Sandbox Code Playgroud)
这意味着您可以应用于fmap列表,Maybe值或Either值.
了解一点范畴论会有所帮助。类别只是一组对象,它们之间有箭头。他们可以对数学中的许多事物进行建模,但出于我们的目的,我们对类型类别感兴趣;Hask是 Haskell 类型的类别,每个类型都是Hask中的一个对象,每个函数都是参数类型和返回类型之间的箭头。例如,Int、Char、[Char]和Bool都是Hask中的对象,并且ord :: Char -> Int、odd :: Int -> Bool、 和repeat :: Char -> [Char]是Hask中箭头的一些示例。
每个类别都有几个属性:
\n\n每个对象都有一个恒等箭头。
箭头组成,因此如果a -> b和b -> c是箭头,那么 也是a -> c。
恒等箭头是组合的左恒等和右恒等。
组合是关联的。
Hask之所以是一个类别,是因为每个类型都有一个恒等函数,并且函数组合。也就是说,id :: Int -> Int和id :: Char -> Char是类别的恒等箭头, 和odd . ord :: Char -> Bool是复合箭头。
(现在忽略我们认为的id是具有类型的多态函数a -> a,而不是一堆具有具体类型的单独函数。这演示了范畴论中的一个概念,称为自然变换,您现在不需要考虑它。)
在范畴论中,函子 F 是两个范畴之间的映射;它将一个类别的每个对象映射到另一个类别的对象,并且还将一个类别的每个箭头映射到另一个类别的箭头。如果a是一个类别中的对象,我们说 F a 是另一类别中的对象。我们还说,如果 f 是第一个类别中的箭头,则在另一个 if F f 中对应的箭头。
并非任何映射都是函子。它必须遵守两个看起来很熟悉的属性。
\n\nh = g \xe2\x88\x98 f属于第一个类别,则h映射到F h = F g \xe2\x88\x98 F f另一个类别。最后,endofunctor是一个将一个类别映射到其自身的函子的特殊名称。在Hask中,类型类捕获了从Hask到HaskFunctor的内函子的思想。类型构造函数本身映射类型,并用于映射箭头。fmap
让我们举Maybe个例子。类型构造函数Maybe是一个endofuntor,因为它将Hask (类型)中的对象映射到Hask (其他类型)中的其他对象。(这一点有点模糊,因为我们没有目标类型的新名称,因此可以将其视为Maybe映射Int到 type Maybe Int。)
为了将箭头映射a -> b到,我们在 的实例中Maybe a -> Maybe b提供了 的定义。\n也映射函数,但使用名称代替。它必须遵守的函子定律与函子定义中列出的两个相同。fmapMaybe IntMaybefmap
fmap id = id (映射id :: Int -> Int到id :: Maybe Int -> Maybe Int.fmap f . fmap g = fmap f . g(也就是说,fmap odd . fmap ord $ x必须返回与类型的fmap (odd . ord) $ x任何可能值相同的值。xMaybe Int作为一个不相关的切线,其他人指出 Haskell 中的某些东西不是函数,即像4和 之类的文字值"hello"。虽然在编程语言中确实如此(例如,您不能4与另一个以 an 作为Int值的函数组合),但在范畴论中,您确实可以用从单位类型()到类型的函数替换值。价值。也就是说,文字值 4 可以被视为一个箭头4 :: () -> Int,当应用于(唯一)类型 的值时,它返回与整数 4 相对应的()类型值。该箭头的组成与任何其他箭头一样;会将单位类型的值映射到指示整数 4 是否为奇数的布尔值。Intodd . 4 :: () -> Bool
从数学上来说,这很好。我们不必为类型定义任何结构;它们就是这样,并且由于我们已经有了定义类型的想法,所以我们不需要单独定义类型的值是什么;我们只是根据功能来定义它们。(不过,您可能会注意到我们仍然需要单位类型的实际值。在我们的定义中可能有一种方法可以避免这种情况,但我对范畴论的了解还不足以解释这种方式或另一种方式。)
\n\n对于我们的编程语言的实际实现,将文字值视为一种优化,以避免每次我们只需要一个常量值时都必须使用4 ()in place 的概念和性能开销。4
| 归档时间: |
|
| 查看次数: |
808 次 |
| 最近记录: |