Haskell中的二进制数反转

Haskell中的二进制数反转,haskell,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)))这意味着作为输入进行反转,任何人请给我提示如何执行此操作?GHC的List模块定义了如下列表上的函数: reverse l = rev l [] where rev []

我为二进制数定义了如下数据类型

data Bin = Nil | O Bin | I Bin 
           deriving (Show, Eq)
我想定义一个函数
reverse::Bin->Bin
,这样当我输入

reverse(I(O(I(I Nil)))
我应该把它取出来
I(I(O(I Nil)))
这意味着作为输入进行反转,任何人请给我提示如何执行此操作?

GHC的
List
模块定义了如下列表上的函数:

reverse l =  rev l []
  where
    rev []     a = a
    rev (x:xs) a = rev xs (x:a)
data Bit = I | O
newtype Bin = List Bit
辅助功能
rev
使用其第二个元素作为累加器,将反向零件存储到当前位置。在每个步骤中,剩余输入列表的第一个元素被添加到传递给递归函数调用的累加器的头部


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

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

reverse l =  rev l []
  where
    rev []     a = a
    rev (x:xs) a = rev xs (x:a)
data Bit = I | O
newtype Bin = List Bit
然后你可以直接使用前奏曲的反向操作

编辑 前奏曲功能的简单替换:

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) | []

因此,列表例程的逻辑直接应用于您的类型。

奇怪的是,您同时定义了列表类型和位类型。我想我应该重用基本库列表类型
[]
,只需将元素设置为您的位类型,如艾丹所示。

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

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
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)

不,问题是不允许我更改数据类型,我必须在给定的数据类型中进行更改
newtype Bin=List Bit
没有意义。你可能是指
type Bin=List Bit
newtype Bin=List[Bit]
newtype Bin=Bin(List Bit)
或类似的意思。我不确定我是否可以在这里应用列表理解,因为我有类似
(I(O(I(I Nil)))的输入。
是的,你可能无法使用列表理解。只是为了内部信息,尽管这是其他人的定义,但他们将列表和二进制数的概念结合起来,这样更容易将它们分开,然后合并在一起。这基本上就是哈斯克尔的观点:作品的构成。如果必须键入更好的定义(Aidan Cully的解决方案),我可能根本不会创建任何新类型:
Bool
已经是合适的位类型,
[]
已经是合适的列表类型。制作
类型Bin=[Bool]
别名,也许。listToBin可以做成一个折叠:listToBin=foldr(\bd->if b then(id)else(od))[]或者甚至
foldr(\b->if b then I else O)[/code>。或者甚至
foldr(!!)[O,I].fromEnum][/code>,如果你今天感觉特别自由的话。