如何以无点样式编写此函数?

Wil*_*ney 19 haskell

我只是想对我的Haskell代码进行一般性改进,并且想知道以下函数是否可以无点编写?主要是出于好奇心的缘故.

给出了我们想要在我们中使用的两个函数filter:

isZero = (==0)
isOne = (==1)
Run Code Online (Sandbox Code Playgroud)

我们如何在我们的设计示例中使用这两个函数,但是使其无点?

filter (\x -> isZero x || isOne x) [0..100]
Run Code Online (Sandbox Code Playgroud)

Igo*_*dov 23

有一个将代码转换为无点的在线服务Haskell.

它表明: filter (liftM2 (||) isZero isOne) [0..100]

liftA2 (||) isZero isOne或者(||) <$> isZero <*> isOne也是可能的

(||) <$> isZero有类型a0 -> Bool -> Bool,它的组成(||)isZero.该组合采用数字(for isZero)和布尔值(作为另一个参数(||))

所以,它是一样的 \x y -> (||) (isZero x) y

函数类型是一个实例,Applicative Functor我们可以看看它的实现:

instance Applicative ((->) r) where  
    pure x = (\_ -> x)  
    f <*> g = \x -> f x (g x)
Run Code Online (Sandbox Code Playgroud)

所以,(||) <$> isZero <*> isOne是一样的,\x -> ((||) <$> isZero) x (isOne x)一样的\x -> (||) (isZero x) (isOne x)

因此,如果存在z x = y (f x) (g x),它可以转换为无点:z = y <$> f <*> g


ram*_*ion 7

另一种无点形式是使用a -> Any幺半群:

? import Data.Monoid (Any(..))
? :t getAny . (Any . isZero <> Any . isOne)
getAny . (Any . isZero <> Any . isOne)
  :: (Num a, Eq a) => a -> Bool
? filter (getAny . (Any . isZero <> Any . isOne)) [0..100]
[0,1]
Run Code Online (Sandbox Code Playgroud)

它比Applicative解决方案长一点,但我认为当你有更多的条件要结合时,它会更容易理解.相比

getAny . (Any . isZero <> Any . isOne <> Any . isSquare <> Any . isPrime)
Run Code Online (Sandbox Code Playgroud)

要么

getAny . foldMap (Any .) [isZero, isOne, isSquare, isPrime]
Run Code Online (Sandbox Code Playgroud)

liftA2 (||) (liftA2 (||) (liftA2 (||) isZero isOne) isSquare) isPrime
Run Code Online (Sandbox Code Playgroud)

要么

liftA2 (||) isZero $ liftA2 (||) isOne $ liftA2 (||) isSquare isPrime
Run Code Online (Sandbox Code Playgroud)

虽然说实话,如果我有很多这样的事情,我很想定义<||> = liftA2 (||)和做

isZero <||> isOne <||> isSquare <||> isPrime
Run Code Online (Sandbox Code Playgroud)