Получил тип Int -> Int вместо Integer и не знаю почему - PullRequest
0 голосов
/ 20 июня 2019

Я написал этот двоично-десятичный преобразователь, получив ошибку компилятора. Я не знаю, откуда он приходит.

binaryToInteger :: [Bool] -> Integer
binaryToInteger (x:xs) = foldr (\x y z -> (fromEnum x) * 2^y + z) 0 [0..length (x:xs)] 

На самом деле программа должна вернуть десятичный результат двоичного числа.Пример дано: binaryToInteger [True, True, False] == 1 (2 ^ 2) + 1 * (2 ^ 1) + 0 * (2 ^ 0) == 6 *

Мое сообщение об ошибке следующее: Не удалось найти ожидаемый тип Integer' with actual type Int -> Int '

  * Probable cause: `foldr' is applied to too few arguments
  In the expression:
    foldr (\ x y z -> (fromEnum x) * 2 ^ y + z) 0 [0 .. length (x : xs)]
  In an equation for `binaryToInteger':
      binaryToInteger (x : xs)
        = foldr
            (\ x y z -> (fromEnum x) * 2 ^ y + z) 0 [0 .. length (x : xs)]

1 Ответ

1 голос
/ 23 июня 2019

Алгоритм выглядит так:

  • вы начинаете с a = 0 («a» означает «аккумулятор»)
  • для True: удвоить a и добавить к нему 1
  • для False: просто удвойте

Пример: [True, False, True]

  • a = 0
  • True => a становится 1 (потому что 0 * 2 + 1 = 1)
  • False => a становится 2 (потому что 1 * 2 = 2)
  • True => a становится 5 (потому что 2 * 2 + 1 = 5)
  • a = 5 - это решение

В коде на Haskell:

import Data.List (foldl')

binaryToInteger :: [Bool] -> Integer
binaryToInteger xs = foldl' f 0 xs where
    f a True  = a * 2 + 1
    f a False = a * 2

Не используйте возведение в степень (^), потому что это плохо сказывается на производительности. Я использовал левый сгиб, потому что он лучше подходит для этой проблемы. Функция foldl' обладает дополнительным преимуществом: она строгая и, следовательно, не вносит утечку пространства.

...