Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
152 views
in Technique[技术] by (71.8m points)

combinators - In Haskell performing `and` and `or` for boolean functions

I just wrote the following two functions:

fand :: (a -> Bool) -> (a -> Bool) -> a -> Bool
fand f1 f2 x = (f1 x) && (f2 x)

f_or :: (a -> Bool) -> (a -> Bool) -> a -> Bool
f_or f1 f2 x = (f1 x) || (f2 x)

They might be used to combined the values of two boolean functions such as:

import Text.ParserCombinators.Parsec
import Data.Char

nameChar = satisfy (isLetter `f_or` isDigit)

After looking at these two functions, I came to the realization that they are very useful. so much so that I now suspect that they are either included in the standard library, or more likely that there is a clean way to do this using existing functions.

What was the "right" way to do this?

question from:https://stackoverflow.com/questions/5710078/in-haskell-performing-and-and-or-for-boolean-functions

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

One simplification,

f_and = liftM2 (&&)
f_or  = liftM2 (||)

or

      = liftA2 (&&)         
      = liftA2 (||)

in the ((->) r) applicative functor.


Applicative version

Why? We have:

instance Applicative ((->) a) where
    (<*>) f g x = f x (g x)

liftA2 f a b = f <$> a <*> b

(<$>) = fmap

instance Functor ((->) r) where
    fmap = (.)

So:

  f g -> liftA2 (&&) f g
= f g -> (&&) <$> f <*> g          -- defn of liftA2
= f g -> ((&&) . f) <*> g          -- defn of <$>
= f g x -> (((&&) . f) x) (g x)    -- defn of <*> - (.) f g = x -> f (g x)
= f g x -> ((&&) (f x)) (g x)      -- defn of (.)
= f g x -> (f x) && (g x)          -- infix (&&)

Monad version

Or for liftM2, we have:

instance Monad ((->) r) where
    return = const
    f >>= k =  r -> k (f r) r

so:

  f g -> liftM2 (&&) f g
= f g -> do { x1 <- f; x2 <- g; return ((&&) x1 x2) }               -- defn of liftM2
= f g -> f >>= x1 -> g >>= x2 -> return ((&&) x1 x2)              -- by do notation
= f g -> (
 -> (x1 -> g >>= x2 -> return ((&&) x1 x2)) (f r) r)  -- defn of (>>=)
= f g -> (
 -> (x1 -> g >>= x2 -> const ((&&) x1 x2)) (f r) r)   -- defn of return
= f g -> (
 -> (x1 ->
               (
 -> (x2 -> const ((&&) x1 x2)) (g r) r)) (f r) r) -- defn of (>>=)
= f g x -> (
 -> (x2 -> const ((&&) (f x) x2)) (g r) r) x         -- beta reduce
= f g x -> (x2 -> const ((&&) (f x) x2)) (g x) x                   -- beta reduce
= f g x -> const ((&&) (f x) (g x)) x                               -- beta reduce
= f g x -> ((&&) (f x) (g x))                                       -- defn of const
= f g x -> (f x) && (g x)                                           -- inline (&&)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...