【问题标题】:Binary to Decimal in Haskell without using recursion or list comprehensionsHaskell中的二进制到十进制而不使用递归或列表推导
【发布时间】:2019-06-19 19:55:30
【问题描述】:

我目前正在做一项家庭作业,该作业要求我实现一个无需使用列表推导或递归即可将二进制转换为十进制的函数。

我尝试过使用折叠,明确地使用foldr,来实现这一点,但不能完全得到正确的结果。在related thread 我发现了以下内容

bintodec :: [Bool] -> Int
bintodec = foldr (\x y -> fromEnum x + 2*y) 0

这似乎是一个很好的起点,但对我来说似乎没有产生正确的结果。它似乎适用于任何给定的奇数,其中列表仅包含Trues,但不适用于其他任何东西。

分配的函数也应该有这个签名:

binarytoInteger :: [Bool] -> Integer

我试图通过在各个点使用toInteger 函数来使用上述定义来实现,但实际上永远无法匹配函数定义的类型。

我很乐意为您提供正确方向的提示!

【问题讨论】:

  • 在您的bintodec 中,它适用于第一个Bool 最低有效位 (LSB)。
  • foldr (\x y -> (if x then 1 else 0) + 2*y) 0 . reverse.
  • foldr 是递归的。您的意思是不允许使用显式递归吗?
  • 是的,我知道,应该澄清一下。没有显式递归

标签: haskell


【解决方案1】:

这似乎是一个很好的起点,但对我来说似乎没有产生正确的结果。它似乎适用于任何给定的奇数,其中列表仅包含 True,但不适用于其他任何内容。

它确实有效,因为它确实将二进制列表转换为整数。但在您的函数中,first 元素是 最低有效位 (LSB)

例如,我们可以在这里使用fold

import Data.Bool(bool)

bin2dec :: (Foldable f, Integral i) => f Bool -> i
bin2dec = foldl (\a -> (+) (2*a) . bool 0 1) 0

例如:

Prelude Data.Bool> bin2dec [False]
0
Prelude Data.Bool> bin2dec [True]
1
Prelude Data.Bool> bin2dec [True, False]
2
Prelude Data.Bool> bin2dec [True, True]
3
Prelude Data.Bool> bin2dec [True, False, False]
4
Prelude Data.Bool> bin2dec [True, False, True]
5
Prelude Data.Bool> bin2dec [True, True, False]
6
Prelude Data.Bool> bin2dec [True, True, True]
7 

【讨论】:

  • 所以我基本上是“从错误的一面”接近这个,因为 cmets 和这个答案要么使用 reversefoldl?我现在将如何将您的解决方案更改为我必须创建的函数所需的类型签名?
  • @cluu:类型签名比较通用,所以bin2dec可以支持[Bool] -> Int[Bool] -> Integer等。
  • @cluuu: foldl 在概念上从左到右运行在列表上,而foldr 在概念上从右到左运行。
  • 现在看来很清楚了,只有最后一件事:布尔部分。快速搜索告诉我它替换了if p then y else x 语句,在这种特殊情况下我的p 是什么?
  • @cluuu 您的fromEnum 很好。如果您不想,无需使用ifbool。只需在将 Int 转换为 Integer(或其他任何 Num 类型)之后调用 fromIntegral
猜你喜欢
  • 2016-05-03
  • 2015-01-15
  • 1970-01-01
  • 2014-12-05
  • 1970-01-01
  • 2022-11-14
  • 2017-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多