您是否有一个与此函数对应的索引的封闭形式解?如果有,您可以使用Enum
派生来简化事情。例如,
import Prelude hiding (Either(..))
data Dir = Right
| Front
| Up
| Left
| Back
| Down
deriving (Show, Eq, Ord, Enum)
inv :: Dir -> Dir
inv x = toEnum ((3 + fromEnum x) `mod` 6)
请注意,这取决于构造函数的顺序!
*Main> inv Left
Right
*Main> inv Right
Left
*Main> inv Back
Front
*Main> inv Up
Down
这段代码非常类似于C语言,利用了构造函数的顺序,并且不太像Haskell。一种折中的方法是使用更多类型,定义构造函数和它们的镜像之间的映射,避免使用算术运算。
import Prelude hiding (Either(..))
data Dir = A NormalDir
| B MirrorDir
deriving Show
data NormalDir = Right | Front | Up
deriving (Show, Eq, Ord, Enum)
data MirrorDir = Left | Back | Down
deriving (Show, Eq, Ord, Enum)
inv :: Dir -> Dir
inv (A n) = B (toEnum (fromEnum n))
inv (B n) = A (toEnum (fromEnum n))
例如。
*Main> inv (A Right)
B Left
*Main> inv (B Down)
A Up
所以至少我们不必做算术运算。并且类型区分镜像案例。但是,这非常不符合Haskell的风格。枚举案例也是完全可以的!毕竟其他人在某个时候也会阅读你的代码...
Sign
的数据构造函数较少是次要的(虽然肯定有益)。 关键观察是Left
和Right
之间的密切关系应该反映在它们的类型中,同样地,例如Left
和Top
之间的远离关系也是如此。 类型系统可帮助处理不变量:使用更多类型,可以表达更精确的不变量。 - Lambdageek