Lan*_*dei 21 haskell coding-style pointfree
我不时偶然发现我想要表达的问题"请使用两次最后一个参数",例如为了编写无点样式或避免使用lambda.例如
sqr x = x * x
Run Code Online (Sandbox Code Playgroud)
可写成
sqr = doubleArgs (*) where
doubleArgs f x = f x x
Run Code Online (Sandbox Code Playgroud)
或者考虑这个稍微复杂的功能(取自这个问题):
ins x xs = zipWith (\ a b -> a ++ (x:b)) (inits xs) (tails xs)
Run Code Online (Sandbox Code Playgroud)
如果有这样的函数,我可以写这个代码pointfree:
ins x = dup (zipWith (\ a b -> a ++ (x:b))) inits tails where
dup f f1 f2 x = f (f1 x) (f2 x)
Run Code Online (Sandbox Code Playgroud)
但是因为我在Hoogle中找不到像doubleArgs或dup这样的东西,所以我猜我可能会错过这里的伎俩或成语.
luq*_*qui 30
来自Control.Monad:
join :: (Monad m) -> m (m a) -> m a
join m = m >>= id
instance Monad ((->) r) where
return = const
m >>= f = \x -> f (m x) x
Run Code Online (Sandbox Code Playgroud)
拓展:
join :: (a -> a -> b) -> (a -> b)
join f = f >>= id
= \x -> id (f x) x
= \x -> f x x
Run Code Online (Sandbox Code Playgroud)
所以,是的,Control.Monad.join.
哦,对于你的无意义的例子,你尝试过使用applicative notation(from Control.Applicative):
ins x = zipWith (\a b -> a ++ (x:b)) <$> inits <*> tails
Run Code Online (Sandbox Code Playgroud)
(我也不知道为什么人们如此喜欢a ++ (x:b)而不是a ++ [x] ++ b......它不会更快 - 内衬会照顾它 - 后者更加对称!哦,好吧)
ste*_*ley 12
你所谓的'doubleArgs'通常被称为dup - 它是W组合子(在模拟鸟模拟中称为鸣鸟) - "基本复制器".
你称之为'dup'的实际上就是'starling-prime'组合.
Haskell有一个相当小的"组合基础",参见Data.Function,加上一些Applicative和Monadic操作,通过Applicative和Monad的函数实例添加更多"标准"组合器(来自Applicative的<*>是S - starling组合器,用于功能实例,liftA2&liftM2是starling-prime).社区似乎没有太多的热情来扩展Data.Function,所以虽然组合器很有趣,但实际上我更喜欢在组合器不能直接使用的情况下长时间使用.
这是我问题第二部分的另一个解决方案:箭头!
import Control.Arrow
ins x = inits &&& tails >>> second (map (x:)) >>> uncurry (zipWith (++))
Run Code Online (Sandbox Code Playgroud)
的&&&("扇出")分配一个参数两个功能,并返回对结果.>>>("然后")反转功能应用程序顺序,允许从左到右进行一系列操作.second仅适用于一对的第二部分.当然,你需要一个uncurry最终在一个期望两个参数的函数中提供该对.