我需要编写一个接受两个约束的函数,并返回第三个约束,只有前两个约束也满足时才会满足。我可以编写一个辅助函数来测试前两个约束是返回true还是false,但问题是测试可能是任何东西所以我不能只是传入一些东西来测试它。有没有办法以某种方式组合任何类型的两个函数/约束?
我希望我有意义。
答案 0 :(得分:5)
假设“约束”是指某种谓词,你可以轻松编写一个函数,它结合了两个谓词来创建一个新的谓词。
type Pred a = a -> Bool
both :: Pred a -> Pred a -> Pred a
both p1 p2 x = p1 x && p2 x
快速测试运行:
*Main Data.Char> both odd (> 3) 5
True
*Main Data.Char> both isAlpha isUpper 'b'
False
答案 1 :(得分:3)
强制性的神秘答案:
import Control.Arrow
import Data.Composition
both :: (a -> Bool) -> (a -> Bool) -> a -> Bool
both = uncurry (&&) .** (&&&)
有一天,我会开始正确地记录我的Data.Composition库(it's on hackage!),但基本上(.**) f g x y z = f (g x y z)
以下是它的工作原理(简化了&&&&& on the functions)
(&&&) f g x = (f x, g x)
uncurry f (x,y) = f x y
(.**) f g x y z = f (g x y z)
both = uncurry (&&) .** (&&&)
-- undo infix notation
both = (.**) (uncurry (&&)) (&&&)
-- definition of .**, with f = (uncurry (&&)), g = (&&&), x = p1, y = p2, z = v
both = \p1 p2 v -> (uncurry (&&)) ((&&&) p1 p2 v)
-- definition of &&&, with f = p1, g = p2, x = v
both = \p1 p2 v -> (uncurry (&&)) (p1 v, p2 v)
-- definition of uncurry, with f = (&&)
both = \p1 p2 v -> (\(x, y) -> (&&) x y) (p1 v, p2 v)
-- function application, bind x = p1 v, y = pw v
both = \p1 p2 v -> (&&) (p1 v) (p2 v)
-- rewrite without lambda, move && to infix position
both p1 p2 v = p1 v && p2 v
我们现在已经达到了hammar的定义。 :)
答案 2 :(得分:0)
如果您有两种类型的测试:
constraint1 :: a -> Bool
constraint2 :: b -> Bool
你希望建立一个第三个收入,这是两者的结合,然后只使用(&&)
:
constraint3 :: a -> b -> Bool
constraint3 a b = constraint1 a && constraint2 b