Специальный полиморфизм Хаскелла по значениям, вычисление длины списка специального полиморфизма - PullRequest
0 голосов
/ 15 ноября 2018

Я пытаюсь понять одно явление из моего кода ниже:

{-# LANGUAGE NoMonomorphismRestriction #-}

import Control.Arrow
import Control.Monad
import Data.List
import qualified Data.Map as M
import Data.Function
import Data.Ratio

class (Show a, Eq a) => Bits a where
    zer :: a
    one :: a

instance Bits Int where
    zer = 0
    one = 1

instance Bits Bool where
    zer = False
    one = True

instance Bits Char where
    zer = '0'
    one = '1'

Когда я пытаюсь это сделать:

b = zer:[]

Это работает отлично, но когда я пытаюсь:

len = length b

Я получаю эту ошибку:

<interactive>:78:8: error:
    • Ambiguous type variable ‘a0’ arising from a use of ‘b’
      prevents the constraint ‘(Bits a0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘a0’ should be.
      These potential instances exist:
        instance [safe] Bits Bool -- Defined at main.hs:18:10
        instance [safe] Bits Char -- Defined at main.hs:22:10
        instance [safe] Bits Int -- Defined at main.hs:14:10
    • In the first argument of ‘length’, namely ‘b’
      In the expression: length b
      In an equation for ‘it’: it = length b

Может кто-нибудь объяснить мне, почему можно создать список из значений zer и one ,но если я хочу вычислить длину списка, я получаю ошибку?

1 Ответ

0 голосов
/ 15 ноября 2018

Возможно, немного проще понять значение этой ошибки в следующем примере:

roundTrip :: String -> String
roundTrip = show . read

Итак roundTrip read s String, а затем show s обратно в (предположительно идентичные) String.

Но read - это полиморфная функция: она анализирует входную строку способом, который зависит от типа вывода. Синтаксический анализ Int - это совсем другой запрос, чем синтаксический анализ Bool!

Разработчик решает, какую конкретную реализацию read использовать, рассматривая предполагаемый тип возврата read. Но в выражении show . read промежуточным типом может быть любой тип a, который реализует как Show, так и Read. Как компилятор должен выбирать реализацию?

Вы можете утверждать, что в вашем примере это не имеет значения, потому что length :: [a] -> Int обрабатывает аргумент типа единообразно. length [zer] всегда 1, независимо от того, через какой экземпляр Bits вы проходите. Такая ситуация сложна для обнаружения компилятором в целом, поэтому проще и предсказуемее просто всегда отвергать неоднозначные типы.

Вы можете решить проблему, указав конкретную аннотацию типа.

> length ([zer] :: [Bool])
1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...