在玩Pointfree时,我遇到了一段我似乎无法理解的代码.
:pl map (\x -> x * x) [1..10]
-- map (join (*)) [1..10]
Run Code Online (Sandbox Code Playgroud)
我的主要问题是我不知道join这里的工作方式.据我所知,它"移除"了一层monadic包装(m (m a)to m a).我觉得它归结为类似的东西[1..10] >>= (\x -> [x * x]),但我真的不知道如何引入"额外的层".我明白了join x = x >>= id,但是我仍然坚持如何"复制"每个值,以便(*)得到两个参数.这已经困扰了我大约半个小时了,我对自己很生气,因为我觉得我有所有的拼图,但似乎无法将它们放在一起......
PS别担心,我不会真正使用这个免费版本,这是纯粹的好奇心,并试图更好地理解Haskell.
我正在学习使用F#进行功能编程的第一步 - 我刚刚遇到了Forward Pipe(|>)和Forward Composition(>>)运算符.起初我以为它们只是糖而不是对最终运行的代码产生影响(尽管我知道管道有助于类型推断).
但是我遇到了这篇SO文章: 函数式编程中"点自由"风格的优点和缺点是什么? 其中有两个有趣且内容丰富的答案(而不是为我简化的事情,开启了围绕"无点"或"无意义"风格的整套蠕虫)我从这些(和其他阅读)带回家是无点的是一个争论的领域.与lambas一样,无点样式可以使代码更容易理解,也可以更难,具体取决于使用情况.它可以帮助有意义地命名.
但我的问题涉及对第一个答案的评论:AshleyF在答案中表示:
"在我看来,组合可能会降低GC的压力,使编译器更明显的是不需要像流水线那样产生中间值; 帮助使所谓的"砍伐森林"问题更容易处理."
加斯奇回复:
"关于改进编译的部分根本不是真的.在大多数语言中,无点样式实际上会降低性能.Haskell在很大程度上依赖于优化,因为它是使这些东西的成本可以承受的唯一方法.充其量,那些组合器被内联,你得到一个相同的有点版本"
任何人都可以扩展性能影响吗?(一般而言,特别是对于F#)我只是假设它是一种写作风格的东西,编译器会将两个习语解开成等效的代码.
有没有办法简化以下代码?
filenames是文件名(字符串)的列表,例如["foo.txt","bar.c","baz.yaml"]
filenames.map { |f| File.size(f) }
Run Code Online (Sandbox Code Playgroud)
有没有办法将"File.size"变成proc或block?对于现有对象的方法,我可以做到&:method.模块级方法有类似的东西吗?
我正在学习Haskell.我很抱歉提出一个非常基本的问题,但似乎无法找到答案.我有一个定义的函数f:
f x = g x x
Run Code Online (Sandbox Code Playgroud)
其中g是已定义的2个参数的函数.我如何写这个免费的风格?编辑:不使用lambda表达式.
谢谢
有点的表示法:
absoluteError x y = abs (x-y)
一个不明确的无点符号示例:
absoluteError' = curry (abs . uncurry (-))
我正在研究Project Euler问题并最终得到一个Haskell文件,其中包含一个如下所示的函数:
matches :: (a -> a -> Bool) -> a -> [(a, Int)] -> Int
matches f cs = foldr (\(cs', n) a -> fromBool (f cs cs') * n + a) 0
Run Code Online (Sandbox Code Playgroud)
随着fromBool进口Foreign.Marshal.Utils只是为了快速转换True到1和False到0.
我试图从我的解决方案中获得更多的速度,所以我尝试切换foldr到foldl'(在过程中切换参数),因为我认为foldr在数字上使用没有多大意义.
根据GHC的分析器,从切换foldr到foldl'使我分配的内存超过两倍.
为了好玩,我还决定用函数的pointfree版本替换lambda:
matches :: (a -> a -> Bool) -> a -> [(a, Int)] -> Int
matches f cs = foldr ((+) …Run Code Online (Sandbox Code Playgroud) 鉴于:
data TwoInts = TwoInts Int Int
add'em :: TwoInts -> Int
add'em (TwoInts a b) = a+b
Run Code Online (Sandbox Code Playgroud)
是否可以写add'em而不必命名a和b.就像是:
add'em TwoInts = (+) -- (Note: Fails to type check)
Run Code Online (Sandbox Code Playgroud) 使用多个模式匹配,即使没有点,也不可能有不同数量的参数!
foo True b = b + 2
foo _ = id
Run Code Online (Sandbox Code Playgroud)
不起作用的例子.但
foo True = (+2)
foo _ = id
Run Code Online (Sandbox Code Playgroud)
确实.有时我们只能在函数的一个部分使用无点,所以......
为什么?GHC太难了吗?:'(
我能够理解Haskell中无点函数的基础知识:
addOne x = 1 + x
Run Code Online (Sandbox Code Playgroud)
当我们在等式的两边看到x时,我们简化它:
addOne = (+ 1)
Run Code Online (Sandbox Code Playgroud)
令人难以置信的是,在不同的部分中使用相同参数两次的函数可以无点编写!
让我把这个average函数作为一个基本的例子写成:
average xs = realToFrac (sum xs) / genericLength xs
Run Code Online (Sandbox Code Playgroud)
似乎无法简化xs,但http://pointfree.io/提出:
average = ap ((/) . realToFrac . sum) genericLength
Run Code Online (Sandbox Code Playgroud)
这样可行.
据我所知,这说明average与调用ap两个函数相同,即(/) . realToFrac . sum和的组合genericLength
不幸的是,这个ap函数对我没有任何意义,文档http://hackage.haskell.org/package/base-4.8.1.0/docs/Control-Monad.html#v:ap状态:
ap :: Monad m => m (a -> b) -> m a -> m b
In many situations, the liftM operations can be …Run Code Online (Sandbox Code Playgroud) 这是代码:
{-# LANGUAGE FlexibleContexts #-}
import Data.Int
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Generic as V
{-# NOINLINE f #-} -- Note the 'NO'
--f :: (Num r, V.Vector v r) => v r -> v r -> v r
--f :: (V.Vector v Int64) => v Int64 -> v Int64 -> v Int64
--f :: (U.Unbox r, Num r) => U.Vector r -> U.Vector r -> U.Vector r
f :: U.Vector Int64 -> U.Vector Int64 -> U.Vector Int64 …Run Code Online (Sandbox Code Playgroud)