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>,如果你今天感觉特别自由的话。