【问题标题】:Case between two unrelated types in HaskellHaskell中两种不相关类型之间的案例
【发布时间】:2013-08-02 22:07:18
【问题描述】:

是否可以在 Haskell 中的两个不相关类型之间使用case 表达式,就像在这个例子中(不工作)代码:

data A = A
data B = B

f x = case x of
  A -> 1
  B -> 2

main = do
  print $ test A
  return ()

我知道我可以在这里使用Either,但是这段代码并不是要使用的——我想深入学习 Haskell 类型系统,看看能做些什么。

【问题讨论】:

  • 问问自己:x 的类型是什么?
  • @delan - 这正是我要回答的问题 - 我在想也许有一些我还不知道的 Haskell 扩展或功能,这会让我做那种事的东西:)

标签: haskell types type-systems


【解决方案1】:

您可以使用 Typeable,而不是为 f 编写自己的类型类 得到 ghc 一些支持的类。您不需要在这里使用 Dynamic ,但在 在某些情况下需要它。

{-# LANGUAGE DeriveDataTypeable #-}
import Data.Dynamic

data A = A deriving (Typeable)
data B = B deriving (Typeable)

f x | Just A <- fromDynamic x = 1
    | Just B <- fromDynamic x = 2

f2 x | Just A <- cast x = 1
     | Just B <- cast x = 2

main = do
  print $ f (toDyn A)
  print $ f2 A

【讨论】:

    【解决方案2】:

    不,这对于普通的 case 语句是不可能的,但是你可以使用类型类来破解这种事情:

    data A = A
    data B = B
    
    class Test a where
        test :: a -> Int
    
    instance Test A where test = const 1
    instance Test B where test = const 2
    
    main = print $ test A
    

    但你应该只在它真的需要的情况下使用它,因为它很快就会变得混乱并且你最终需要对类型系统进行大量扩展(UndecidableInstances、OverlappingInstances、...)

    【讨论】:

      【解决方案3】:

      AB 是不同的类型。如果你想要一个可以接受多种类型值的函数,你需要一个类型类。

      data A = A
      data B = B
      
      class F a where
        f :: a -> Int
      
      instance F A where
        f _ = 1
      
      instance F B where
        f _ = 2
      
      main = do
        print $ f A
      

      【讨论】:

        猜你喜欢
        • 2018-10-31
        • 2015-02-05
        • 2019-12-30
        • 2018-07-11
        • 2013-12-24
        • 2012-08-21
        • 1970-01-01
        • 1970-01-01
        • 2021-01-01
        相关资源
        最近更新 更多