在Haskell中反转二进制数

时间:2009-12-13 21:41:12

标签: haskell

我已经为二进制数定义了数据类型,如下所示

data Bin = Nil | O Bin | I Bin 
           deriving (Show, Eq)

我想定义一个函数reverse :: Bin -> Bin,这样当我提供像

这样的输入时

reverse (I (O (I (I Nil))))我应该了解情况 I (I (O (I Nil)))这意味着作为输入反转,任何身体请告诉我如何做到这一点?

6 个答案:

答案 0 :(得分:8)

你为什么这样做?为什么不这样:

data Bit = I | O
newtype Bin = List Bit

然后你可以直接使用Prelude的反向操作......

修改的 从Prelude的函数中简单替换:

reverse x = rev x []
  where
    rev [] a = a
    rev (x:xs) a = rev xs (x:a)

的产率:

reverse x = rev x Nil
  where
    rev Nil a = a
    rev (I xs) a = rev xs (I a)
    rev (O xs) a = rev xs (O a)

问题是,你的类型与列表类型非常相似:

data List a = a : (List a) | []

所以List例程的逻辑直接应用于你的类型。

答案 1 :(得分:6)

data Bin = Nil | O Bin | I Bin deriving (Show, Eq)
reverse :: Bin -> Bin
reverse x = rev Nil x
    where
        rev a Nil = a
        rev a ( O b ) = rev ( O a ) b
        rev a ( I b ) = rev ( I a ) b

答案 2 :(得分:4)

binToList Nil = []
binToList (O a) = False : binToList a
binToList (I a) = True : binToList a

listToBin [] = Nil
listToBin (False : xs) = O (listToBin xs)
listToBin (True : xs) = I (listToBin xs)

reverseBin = listToBin . reverse . binToList

答案 3 :(得分:2)

GHC的List模块定义了这样的列表上的reverse函数:

reverse l =  rev l []
  where
    rev []     a = a
    rev (x:xs) a = rev xs (x:a)

辅助函数rev使用其第二个元素作为累加器,将反转部分存储到当前位置。在每一步中,剩余输入列表的第一个元素被添加到累加器的头部,并传递给递归函数调用。

同样的原则可以应用于二进制数字类型以反转数字的顺序。

答案 4 :(得分:1)

奇怪的是,您要定义列表类型和位类型。我想我会重用基础库列表类型[],只需将元素设置为您的位类型,如上面Aidan所示。

答案 5 :(得分:0)

这是一个可能的解决方案:

reverseBin :: Bin -> Bin 
reverseBin b = revBin b Nil
            where revBin Nil acc   = acc
                  revBin (I b) acc = revBin b (I acc)
                  revBin (O b) acc = revBin b (O acc)