Gab*_*iMe 129 haskell functional-programming
我不明白"提升"是什么.在了解"电梯"是什么之前我应该先了解单子吗?(我对monads也完全无知:)或者有人可以用简单的词语向我解释一下吗?
Pau*_*son 173
提升更多的是一种设计模式,而不是一种数学概念(虽然我希望周围的人现在可以通过展示升降机是一类什么类型来反驳我).
通常,您有一些带参数的数据类型.就像是
data Foo a = Foo { ...stuff here ...}
Run Code Online (Sandbox Code Playgroud)
假设你发现了很多的用途,Foo采取数值类型(Int,Double等等),并保留其编写解开这些数字,添加或将它们相乘,然后包装它们备份代码.您可以通过编写一次unwrap-and-wrap代码来使其短路.此功能传统上称为"提升",因为它看起来像这样:
liftFoo2 :: (a -> b -> c) -> Foo a -> Foo b -> Foo c
Run Code Online (Sandbox Code Playgroud)
换句话说,你有一个带有两个参数函数的函数(比如(+)运算符)并将它转换为Foos的等价函数.
所以现在你可以写
addFoo = liftFoo2 (+)
Run Code Online (Sandbox Code Playgroud)
编辑:更多信息
你当然可以拥有liftFoo3,liftFoo4等等.然而,这通常是不必要的.
从观察开始
liftFoo1 :: (a -> b) -> Foo a -> Foo b
Run Code Online (Sandbox Code Playgroud)
但这完全一样fmap.而不是liftFoo1你会写
instance Functor Foo where
fmap f foo = ...
Run Code Online (Sandbox Code Playgroud)
如果你真的想要完全规律,你可以说
liftFoo1 = fmap
Run Code Online (Sandbox Code Playgroud)
如果你可以Foo成为一个仿函数,也许你可以把它变成一个应用函子.事实上,如果你可以写,liftFoo2那么applicative实例看起来像这样:
import Control.Applicative
instance Applicative Foo where
pure x = Foo $ ... -- Wrap 'x' inside a Foo.
(<*>) = liftFoo2 ($)
Run Code Online (Sandbox Code Playgroud)
(<*>)Foo 的操作员有类型
(<*>) :: Foo (a -> b) -> Foo a -> Foo b
Run Code Online (Sandbox Code Playgroud)
它将包装函数应用于包装值.因此,如果您可以实施,liftFoo2那么您可以根据它来编写.或者你可以直接实现它而不用费心liftFoo2,因为Control.Applicative模块包括
liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
Run Code Online (Sandbox Code Playgroud)
同样有liftA和liftA3.但是你实际上并没有经常使用它们,因为还有另一个操作员
(<$>) = fmap
Run Code Online (Sandbox Code Playgroud)
这可以让你写:
result = myFunction <$> arg1 <*> arg2 <*> arg3 <*> arg4
Run Code Online (Sandbox Code Playgroud)
该术语myFunction <$> arg1返回包含在Foo中的新函数.这反过来可以应用于下一个参数(<*>),依此类推.因此,现在不是为每个arity提供升力功能,而是只有一个菊花链应用程序.
Mar*_*ijn 40
Paul和yairchu都是很好的解释.
我想补充说,被提升的函数可以有任意数量的参数,并且它们不必是相同的类型.例如,您还可以定义liftFoo1:
liftFoo1 :: (a -> b) -> Foo a -> Foo b
Run Code Online (Sandbox Code Playgroud)
通常,在类型类中捕获取1个参数的函数Functor,并调用提升操作fmap:
fmap :: Functor f => (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
注意与liftFoo1类型的相似性.事实上,如果你有liftFoo1,你可以做Foo一个实例Functor:
instance Functor Foo where
fmap = liftFoo1
Run Code Online (Sandbox Code Playgroud)
此外,提升到任意数量的参数的概括被称为应用风格.在掌握具有固定数量参数的函数解除之前,不要费心去做.但是当你这样做的时候,了解一下Haskell有一个很好的章节.该Typeclassopedia是描述另一个很好的文件函子和应用型(以及其他类型的类;向下滚动到文档中的正确章).
希望这可以帮助!
yai*_*chu 24
让我们从一个例子开始:
> import Control.Applicative
> replicate 3 'a'
"aaa"
> :t replicate
replicate :: Int -> b -> [b]
> :t liftA2
liftA2 :: (Applicative f) => (a -> b -> c) -> (f a -> f b -> f c)
> :t liftA2 replicate
liftA2 replicate :: (Applicative f) => f Int -> f b -> f [b]
> (liftA2 replicate) [1,2,3] ['a','b','c']
["a","b","c","aa","bb","cc","aaa","bbb","ccc"]
> ['a','b','c']
"abc"
Run Code Online (Sandbox Code Playgroud)
liftA2将普通类型的函数转换为包含在Applicative诸如列表IO等中的这些类型的函数.
另一个常见的电梯lift来自Control.Monad.Trans.它将一个monad的monadic动作转换为变形monad的动作.
通常,升降机将功能/动作"提升"为"包裹"类型.
了解它的最佳方法,monad等以及理解它们有用的原因,可能是编码和使用它.如果您之前编写过任何您怀疑可以从中受益的内容(即这会使代码更短等),只需尝试一下即可轻松掌握这一概念.
Nas*_*loo 14
提升是一个概念,它允许您将功能转换为另一个(通常更一般)设置中的相应功能
看看http://haskell.org/haskellwiki/Lifting