我写过这个函数:
-- 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
有没有更好的方式表达这个?
答案 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))