2012-10-30 143 views
3

我在Haskell中做的一些计算的一部分产生了一个函数列表,它将Float映射到Float。我想一个参数,适用于所有这些功能,比如:Haskell:映射函数应用程序

-- x :: Float 
-- functions :: [Float -> Float] 
map (\f -> f x) functions 

有没有办法做到这一点而不使用一个扔掉的lambda函数的?我搜索Hoogle我认为签名应该是([a -> b] -> a -> [b])没有运气。

+0

请参阅http://stackoverflow.com/questions/11709350 –

+1

只是单挑,有一个名为'pointfree'('cabal install pointfree')的程序,可以自动执行这些类型的缩减。例如'map(\ f - > f x)fs'根据需要变成'map($ x)fs'。 – huon

回答

9

可以使用$运营商,这仅仅是功能应用:(这预示着x在范围为表达)

map ($ x) functions 

Hoogle唯一能找到的功能,而不是任意表达式。由于您使用的是map,因此您希望搜索诸如(a -> b) -> a -> b之类的函数,而不是涉及列表的任何内容。给定一个正常的函数,将它传递给map使其对列表起作用。

+0

是的,我觉得我对签名有些困惑。谢谢!我理解'$'如何定义优先级,但是在这种情况下它是如何工作的? –

+2

运算符的定义非常简单:'f $ x = f x'。所以它实际上只是功能应用,作为一个操作员。当你部分应用它时,你会得到一些等同于'\ f - > f $ x'的东西;使用上面的定义,这可以解释为'\ f - > f x',这正是你所拥有的。 –

+0

据我所知,'map f xs'对'xs'中的每个'x'都做'f x'。所以它看起来像'$ f x',因此我的困惑! –

6

functions <*> pure x应该这样做。先导入Control.Applicative模块。

也可以这样考虑:

Prelude Control.Applicative> [(1+),(2+)] <*> pure 4 
[5,6] 
Prelude Control.Applicative> [(1+),(2+)] <*> [4] 
[5,6] 
Prelude Control.Applicative> [(1+),(2+)] <*> [4,5] 
[5,6,6,7] 
Prelude Control.Applicative> [(+)] <*> [1,2] <*> [4,5] 
[5,6,6,7] 
Prelude Control.Applicative> (+) <$> [1,2] <*> [4,5] 
[5,6,6,7] 
Prelude Control.Applicative> getZipList $ ZipList [(1+),(2+)] <*> ZipList [4,5] 
[5,7] 
Prelude Control.Applicative> getZipList $ ZipList [(1+),(2+)] <*> pure 4 
[5,6] 

<$>仅仅是fmap的代名词。根据某种语义,<*>适用于左侧的应用函子中的“携带”,以及右侧的内容。对于裸列表,语义与列表monad相同 - 进行所有可能的组合 - 将每个函数从左边应用到右边的每个对象,然后pure x = [x]。对于标记的列表(即,newtyped)为ZipLists,语义是“拉链”应用 - 即一对一pure x = ZipList $ repeat x

+0

好吧,我有时间学习一些monads?谢谢! –

+1

不是单子,应用函子。 :) –

+2

这些函数实际上是为应用函子定义的,而不是单子。应用程序更普遍 - 所有monad也是应用程序,但反之亦然。 –