Function Haskell中使用Horners算法的二进制到十进制转换

Function Haskell中使用Horners算法的二进制到十进制转换,function,haskell,binary,data-conversion,Function,Haskell,Binary,Data Conversion,我试图在这里实现一个函数,它获取表示二进制数的Bool列表,如[True,False,False],并根据Horners方法将其转换为相应的十进制数 函数类型将是[Bool]->Int 我下面介绍的算法是: 霍纳斯算法视觉解释: 到目前为止,我已经实现了这样一种逻辑,它说首先它将检查列表是否为空,或者列表中的一个元素[True],将给出1,[False]将给出0 然后在本例中,binToDecList(x:xs)=binToDecList'x0我如何处理第一个元素,无论这是真是假 binToD

我试图在这里实现一个函数,它获取表示二进制数的Bool列表,如
[True,False,False]
,并根据Horners方法将其转换为相应的十进制数

函数类型将是
[Bool]->Int

我下面介绍的算法是:

霍纳斯算法视觉解释:

到目前为止,我已经实现了这样一种逻辑,它说首先它将检查列表是否为空,或者列表中的一个元素
[True]
,将给出1,
[False]
将给出0

然后在本例中,
binToDecList(x:xs)=binToDecList'x0
我如何处理第一个元素,无论这是真是假

binToDecList :: [Bool] -> Int
binToDecList []      = error "Empty List"
binToDecList [True]  = 1
binToDecList [False] = 0
binToDecList (x:xs)  =  binToDecList' x 0 
binToDecList' x d | x == True = mul (add d 1)
                  | otherwise = mul (add d 0)

add :: Int -> Int -> Int
add x y = x + y

mul :: Int -> Int
mul x = x * 2
我想在下一次迭代中使用
binToDecList'
的结果,在列表的下一个元素上递归调用自己。如何存储结果,然后递归地将其应用于列表的下一个元素。任何形式的帮助都将不胜感激

foldl的*类型告诉我们它必须如何工作

foldl::(b->a->b)->b->[a]->b
显然,
[a]
,作为某事物列表的第三个参数,必须是要交给霍纳算法的
Bool
列表。这意味着类型变量
a
必须是
Bool

类型变量
b
表示可能不同的类型。我们正在尝试将
[Bool]
转换为
Int
,因此
Int
对于
b
来说是一个不错的猜测

foldl
的工作原理是从左边咀嚼一个列表(即从它的头部开始),然后以某种方式将结果与列表中的下一个元素组合起来。第二个参数通常被命名为“零”的
z
,或折叠过程的种子值。当
foldl
到达列表末尾时,它返回累积值

我们可以从语法上看到,第一个参数是一些函数,它对
b
类型和
a
类型的项执行一些操作,以生成
b
。现在,一个忽略
a
项并无条件地生成
b
项的函数是合适的,但不是很有趣

想想霍纳的算法是如何进行的。图中路径弯头处的数字表示上一段中的概念“迄今为止的结果”。我们知道
b
Int
a
Bool
,因此传递给
foldl
的函数必须将
Bool
转换为
Int
,并将其与结果相结合

霍纳算法的第一步似乎是一个特殊情况,需要以不同的方式处理,但
foldl
始终使用相同的函数。如果你想象一个不可见的水平移动(即乘以2)开始“启动泵”,我们可以使类型像拼图一样组合在一起。这很好,因为二次零仍然是零

因此,在
foldl
方面,霍纳算法是

霍纳斯::[Bool]->Int horners=foldl f 0 其中f x b= 设b'=从枚举b 在2*x+b' 请注意,
2*x+b'
组合了后续的水平和垂直移动

这也说明了如何用直接递归来表达它

horners':[Bool]->Int
霍纳斯'[]=0
霍纳斯的l=go 0 l
在哪里,在那边
转到x[]=x
围棋(b:bs)=
设b'=从枚举b
in-go(2*x+b')bs
在这里,内部的
go
循环正在执行左折叠,并将每个下一个
Bool
与到目前为止在
i
中得到的结果相结合



*教学上的简化:实际类型将列表类型概括为
可折叠的

尝试使用
折叠
。如果您只需将
[Bool]
值立即转换为
[Int]
值列表,并使用
映射fromEnum
binToDecList=go,这会简单一些。映射自Enum where go=…
。在中查找
foldl
的文档,然后尝试填充
go
帮助函数缺少的定义:
binToDecList=foldl go 0 where go acc x=…
,我可以用fold函数实现这个功能,但我仍然想知道为什么它不能用显式递归实现?第二,还有一个问题,就是执行一个额外的迭代来乘以结果。我怎么能控制这里。我尝试了这种方法,如果下一个元素是[],那么它将返回到目前为止累积的结果。但它似乎没有按预期运行,可能是调用函数的组合不正确?请引导:foldl(\result x->if x==True然后(mul(add result 1)xs)else(mul(add result 1)xs))0 xs和mul::Int->[Bool]->Int mul x b=if tail(b)/=[]然后x*2 else x。我知道这个逻辑在这里可能不太好,但我现在想这样做,除非我走错了方向。有什么帮助吗?