我正在寻找一种更好的方法来检查给定类型的所有值是否相等.
例如,考虑:
data Foo = Foo {a :: Int, b :: Int, c :: Int, d :: Int}
allFooEqual :: Foo -> Bool
allFooEqual foo = (a foo == b foo) && (a foo == c foo) && (a foo == d foo)
Run Code Online (Sandbox Code Playgroud)
这可行,但它不是一个可扩展的解决方案.有没有更惯用的方式来执行我所缺少的这种行为?
替代:
allFooEqual :: Foo -> Bool
allFooEqual (Foo xa xb xc xd) = all (xa==) [xb,xc,xd]
Run Code Online (Sandbox Code Playgroud)
这将进行比较xa == xb && xa == xc && xa == xd.
另一个:
atMostOne :: Eq a => [a] -> Bool
atMostOne xs = and $ zipWith (==) xs (drop 1 xs)
allFooEqual :: Foo -> Bool
allFooEqual (Foo xa xb xc xd) = atMostOne [xa,xb,xc,xd]
Run Code Online (Sandbox Code Playgroud)
这将进行比较xa == xb && xb == xc && xc == xd.
访问"所有Ints in a Foo"可以利用废弃的样板框架或GHC Generics来完成,但除非你真的有很多领域,否则它看起来有点过分.
allFooEqual :: Foo -> Bool
allFooEqual f = atMostOne [ x
| Just x <- gmapQ (mkQ Nothing (Just :: Int -> Maybe Int)) f ]
Run Code Online (Sandbox Code Playgroud)
这里有很多类型级别的东西,我强烈推荐它,除非真的,真的需要它.