Показать тип ограничения в haskell - PullRequest
0 голосов
/ 15 ноября 2018

Я пытаюсь использовать функцию show для вывода на консоль значения zer или one , но я не могу этого сделать.Вот мой код:

{-# LANGUAGE NoMonomorphismRestriction #-}

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

class 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'

Я пытаюсь использовать функцию show для преобразования нуля или единицы в строку.Итак, я попробовал:

k = zer
show k

но я получил эту ошибку

<interactive>:10:1: error:
    • Ambiguous type variable ‘a0’ arising from a use of ‘show’
      prevents the constraint ‘(Show a0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘a0’ should be.
      These potential instances exist:
        instance (Show k, Show a) => Show (M.Map k a)
          -- Defined in ‘containers-0.5.7.1:Data.Map.Base’
        instance Show Ordering -- Defined in ‘GHC.Show’
        instance Show Integer -- Defined in ‘GHC.Show’
        ...plus 24 others
        ...plus 11 instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the expression: show zer
      In an equation for ‘it’: it = show zer

, поэтому я попытался создать экземпляр для шоу.Поэтому я добавил это в свой код:

instance (Show a) => Show (Bits a) where
    show zer = "0"
    show one = "1"

Но я получил еще одну ошибку

main.hs:25:28: error:
    • Expected a type, but ‘Bits a’ has kind ‘Constraint’
    • In the first argument of ‘Show’, namely ‘Bits a’
      In the instance declaration for ‘Show (Bits a)’

Можете ли вы сказать мне, что я делаю неправильно?

1 Ответ

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

Вы пытаетесь сделать класс экземпляром класса, а не type экземпляром класса.Сравните:

Show a => Show (Bits a) -- Invalid

с

Show a => Show (Maybe a) -- Valid

, где Maybe - это тип данных, тогда как Bits - это имя класса.


Не знаюдумаю, что можно выразить «все, что имеет Bits экземпляр, имеет Show экземпляр», потому что это может привести к перекрывающимся экземплярам : если вы можете определить что-то подобное, то когда вы используете show :: Int -> String компилятор не будет знать, использовать ли экземпляр Prelude Show Int или show, который будет определен как Int, являющийся экземпляром Bits.

Грязный обходной путь может бытьприменять «другое направление»: каждый экземпляр Bits должен быть экземпляром Show, что позволит вам использовать a Show экземпляр вместо своего собственного:

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

main = print (zer :: Int)

хотя для этого требуется явная подпись типа для устранения неоднозначности в типе zer на сайте вызова.

...