abstract:判断 a 和 b 都在 xx里面 ,或者 c 在 xx 里面当然实际可能不止 3 个元素参与判断。怎样用简洁通用的代码实现这个逻辑?直接 按照题目上那样写虽然不报错,但是语义却完全不同In [177]: print (1 and 2) in [1,1,3]FalseIn [178]: print 1 and 22In [179]: print (1 and 2) in [2,3]True这个 (a
判断 a 和 b 都在 xx里面 ,或者 c 在 xx 里面
当然实际可能不止 3 个元素参与判断。
怎样用简洁通用的代码实现这个逻辑?
直接 按照题目上那样写虽然不报错,但是语义却完全不同
In [177]: print (1 and 2) in [1,1,3]
False
In [178]: print 1 and 2
2
In [179]: print (1 and 2) in [2,3]
True
这个 (a and b or c) in cc 一眼看上去类型不太对,先让我们把它写的更加 explicit 一些:
in_(or_(and_(contains(a), contains(b)), contains(c), cc)
可以看出,如果上述式子的类型是 Bool,而且 forsome x. a, b, c :: x; cc :: Set x; contains :: x -> Set x -> Bool,那么一个合理的类型推断是 and_, or_ :: (x -> Bool) -> (x -> Bool) -> x -> Bool; in_ :: forall x. x -> x。
正如 F91 所说,类型清楚之后,剩下的就是填空了。我们先用 Haskell 写一遍:
contains x = foldr combine False where combine x' r = x' == x || r-- Control.Concatenative-- 也可以写成 bi f g h = h <$> f <*> gbi f g h x = f x `h` g xand_ f g = bi f g (&&)or_ f g = bi f g (||)main = print x where x = (contains 1 `and_` contains 2 `or_` contains 3) [1, 3, 5]
写成 Python 就是
import operatordef contains(x): def call(xs): return x in xs return calldef bi(f, g, h): def call(x): return h(f(x), g(x)) return calldef and_(f, g): return bi(f, g, operator.and_)def or_(f, g): return bi(f, g, operator.or_)print(or_(and_(contains(1), contains(2)), contains(3))([1, 3, 5]))