我有自己的类型:
data MyType = ...
现在,我想在if
中使用此类型的值。有可能实现它吗?当然,此刻我得到错误:
Couldn't match expected type ‘Bool’ with actual type ‘MyType’
答案 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!
再次,不要这样做!只需使用一个简单的功能,就可以避免让人头疼不已,并且不会让任何读过你代码的人感到困惑,因为他们没有意识到你改变了语法的语法。语言工作。