Bool班 - 喜欢Num?

时间:2016-05-04 21:34:49

标签: haskell

我有自己的类型:

data MyType = ...

现在,我想在if中使用此类型的值。有可能实现它吗?当然,此刻我得到错误:

 Couldn't match expected type ‘Bool’ with actual type ‘MyType’

2 个答案:

答案 0 :(得分:7)

if / then / else的标准语义特定于Bool。使用GHC,可以使用RebindableSyntax扩展名更改标准语义。引用文档:

  

... -XRebindableSyntax标志导致以下内置语法引用范围内的任何内容,而不是Prelude版本:

     
      
  • 条件(例如if e1 then e2 else e3)表示ifThenElse e1 e2 e3。但case表达式不受影响。
  •   

这是我对所提问题的技术答案。

然而,我的自以为是的答案是你不应该这样做。而是编写类型为MyType -> Bool的谓词;然后使用if predicate myValue then ... else ...。在我看来,这种明确的方式更加明确和惯用;并且作为附带的好处也更灵活,因为你可以有许多不同类型的谓词,而不是将任何一个提升到特殊状态。

答案 1 :(得分:1)

你可以用-XRebindableSyntax来做(虽然你应该听Daniel Wagner而不是这样做):

{-# LANGUAGE RebindableSyntax #-}
module Test where

import qualified Prelude as P


class Decidable b where
    toBool :: b -> P.Bool

instance Decidable P.Bool where
    toBool = P.id

ifThenElse :: Decidable b => b -> a -> a -> a
ifThenElse b ifTrue ifFalse = case toBool b of
    P.True -> ifTrue
    P.False -> ifFalse

data Test = A | B deriving (P.Eq, P.Show)

instance Decidable Test where
    toBool A = P.True
    toBool B = P.False

然后在GHCi中:

> :l decidable.hs
> :set -XRebindableSyntax
> P.putStrLn (if A then "it worked!" else "it failed!")
it worked!

再次,不要这样做!只需使用一个简单的功能,就可以避免让人头疼不已,并且不会让任何读过你代码的人感到困惑,因为他们没有意识到你改变了语法的语法。语言工作。