按fst过滤元组列表

时间:2016-03-16 14:56:02

标签: haskell currying

我想要做的并不是真正解决问题,而是学习如何编写构成/利用基本功能的Haskell代码来实现它。

我有一个函数,它接受元组(String,Int)和String的列表,并返回一个元组,其fst与给定的String匹配。 这对filter和lambda来说相当容易,但我现在要做的是删除最右边的参数,即。我想重构函数,使其成为部分应用函数的组合,这些函数将执行相同的功能。

原始代码是:

getstat :: Player -> String -> Stat
getstat p n = head $ filter (\(n', v) -> n' == n) $ stats p

新代码是:

getstat :: Player -> String -> Stat
getstat p = head . (flip filter $ stats p) . cmpfst
    where cmpfst = (==) . fst . (flip (,)) 0  -- Wrong :-\

想法是翻转过滤器并通过给出元组列表(stats p)来部分应用,然后组成cmpfst。 cmpfst应该是String - > (String,Int) - > Bool,以便在应用String参数时,它变为 - > Bool对于过滤器传入元组有好处,但正如你所看到的 - 我在编写(==)时遇到问题,因此只比较了给定元组的fst。

P.S。我知道第一个代码可能更清晰;这项任务的重点不是编写干净的代码,而是学习如何通过合成解决问题。

编辑:

我很清楚,在一个可能空的列表上寻找一个头是一个糟糕的编程,这将导致崩溃。就像前面提到的一张海报一样,用Maybe monad非常简单而优雅地解决了这个问题 - 这是我以前做过的一项熟悉的任务。

我希望重点关注的是如何使cmpfst主要由基本功能组成。 到目前为止,我得到的最远的是:

getstat :: Player -> String -> Stat
getstat p = head . (flip filter $ stats p) . (\n' -> (==(fst n')) . fst) . (flip (,)) 0

我无法通过合成和部分应用(==)来摆脱(a - > Bool)lambda。对我来说,这表明我要么不明白我在做什么,要么以我想象的方式使用(==)运算符是不可能的。

此外,除非没有确切的解决方案,否则我会接受签名更改解决方案作为正确解决方案。我不想改变函数的签名只是因为它是我的心理练习,而不是生产代码。

2 个答案:

答案 0 :(得分:2)

如果我正在写这个函数,我可能会给它这个类型的签名:

getstat :: String -> Player -> Stat

这使得将定义简化为

变得容易
getstat n = head . filter ((== n) . fst) . stats

答案 1 :(得分:1)

在评论中,您已达到

basic_string( const CharT* s,
              size_type count, 
              const Allocator& alloc = Allocator() );
  

我想知道是否有更好的成分可以消除anon f。

嗯,这是

getstat p = head . (flip filter $ stats p) . (\n (n', v) -> n' == n)

删除\n (n', v) -> n' == n -- for convenience, we flip the == \n (n', v) -> n == n' -- prefix notation \n (n', v) -> (==) n n' -- let's remove pattern matching over (n', v) \n (n', v) -> (==) n $ fst (n', v) \n x -> (==) n $ fst x -- composition, eta \n -> (==) n . fst -- prefix \n -> (.) ((==) n) fst -- composition \n -> ((.) . (==) $ n) fst -- let's force the application to be of the form (f n (g n)) \n -> ((.) . (==) $ n) (const fst $ n) -- exploit f <*> g = \n -> f n (g n) -- AKA the S combinator ((.) . (==)) <*> (const fst) -- remove unneeded parentheses (.) . (==) <*> const fst 作为练习。