如何在不使代码更难阅读的情况下使这个功能无点?

时间:2014-10-07 14:54:07

标签: haskell pointfree

我写过这个函数:

-- Either exact match or is suffix of ".example.com" (mind the dot)
-- This prevents for overlapping like "myexample.com"
isDomainOf :: B.ByteString -> B.ByteString -> Bool
isDomainOf a b = (a == b) || a `B.isSuffixOf` (B.append "." b)

如果我将pointless应用于我得到的函数:

isDomainOf = ap (ap . ((||) .) . (==)) ((. B.append ".") . B.isSuffixOf)

这显然比有点版本更长,更难阅读。

问题是or运算符,因为我不能像这样写(||)的左右两边:

isDomainOf = (==) || (. append ".") . isSuffixOf

有没有更好的方式表达这个?

1 个答案:

答案 0 :(得分:4)

一般方案是你有

foo :: A -> B -> C    -- foo = (==)                           :: BStr->BStr->Bool
bar :: A -> B -> D    -- bar = (\a b -> a`isSuffixOf`(':':b)) :: BStr->BStr->Bool
comb :: C -> D -> E   -- comb = (||)                          :: Bool->Bool->Bool

并想表达\a b -> comb (foo a b) (bar a b)。当然,首先它是一个好主意to hoogle for that specific combinator,但是这对于预期结果来说有点过于疯狂。

为了尝试自己制作一个无点版本(正如bheklir评论,首先考虑这个问题可能不是一个好主意),首先要注意当插值不是很简单时它会变得容易咖喱。

foo' :: (A,B) -> C
bar' :: (A,B) -> D

为什么,如果您统一(A,B) ~ P,我们只需要将foo'bar'并行放置,并将结果提供给comb。使用Arrow组合器,这看起来如此:

        uncurry comb . (foo' &&& bar')

这不是太糟糕。当然,写出所有必要的不作为使得它仍然是一个噩梦:

   curry $ uncurry (||) . (uncurry(==) &&& \(a,b) -> a`isSuffixOf`(':':b))

因为我们仍然有一个lambda,所以它仍然不是无点的;虽然那个当然也可以没有指出:

   curry $ uncurry (||) . (uncurry(==) &&& uncurry(((':':).) . isSuffixOf))
相关问题