In Haskell, how can I map a class of a type to an instance of that type?

I have defined the following classes:

class Configuration c where
  input :: (PortIn pin, Show pin) => c -> pin
  startSt :: (SysState st, Show st) => c -> st

class (Eq pin, Show pin) => PortIn pin

class (Eq st, Show st) => SysState st

The following types and instances:

--inputs
data PIn = PIn { _clk   :: Bit
               , _reset :: Bool
               , _start :: Bool
               , _stop  :: Bool
               } deriving (Eq)
instance PortIn PIn
instance Show PIn where
  show PIn {..} =
    "PIn\n\t _clk = " P.++ show _clk
    P.++ "\n\t _reset = " P.++ show _reset
    P.++ "\n\t _start = " P.++ show _start
    P.++ "\n\t _stop = " P.++ show _stop

--Outputs and state data
data St = St { _cnt_en   :: Bool
             , _count_us :: BitVector 4
             , _stop_d1  :: Bool
             , _stop_d2  :: Bool
             , _count    :: BitVector 4
             } deriving (Eq)

instance SysState St
instance Show St where
 show St {..} =
        "St\n\t _cnt_en = " P.++ show _cnt_en

   P.++ "\n\t _count_us = " P.++ show _count_us
   P.++ "\n\t _stop_d1 = " P.++ show _stop_d1
   P.++ "\n\t _stop_d2 = " P.++ show _stop_d2
   P.++ "\n\t _count = " P.++ show _count

Why can't I create an instance of the configuration here:

data Config = Config { input'  :: PIn
                     , startSt' :: St
                     } deriving (Eq)

instance Show Config where
 show Config {..} =
        "Config:\n input = " P.++ show input'
   P.++ "\n startSt = " P.++ show startSt'

instance Configuration Config where
  input = input'
  startSt = startSt'

I get the following error:

Couldn't match type ‘pin’ with ‘PIn’
  ‘pin’ is a rigid type variable bound by
        the type signature for
          input :: (PortIn pin, Show pin) => Config -> pin
        at Clks_n_regs_4.hs:101:3
Expected type: Config -> pin
  Actual type: Config -> PIn
Relevant bindings include
  input :: Config -> pin (bound at Clks_n_regs_4.hs:101:3)
In the expression: input'
In an equation for ‘input’: input = input'

I would think that I can use the input, because this leads to the fact that PIn, in the case of a pin.

I have a misunderstanding somewhere, hope someone can explain what I am missing.

+4
source share
2 answers

, , , , : . . - :

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}

class (PortIn pin, Show pin, SysState st, Show st) => Configuration c pin st
    | c -> pin, c -> st where
  input   :: c -> pin
  startSt :: c -> st

:

instance Configuration Config PIn St where
  input   = input'
  startSt = startSt'

, , .

. :

{-# LANGUAGE ExistentialQuantification #-}

data PortInShow   = forall a . (PortIn a,   Show a) => PortInShow a
data SysStateShow = forall a . (SysState a, Show a) => SysStateShow a

class Configuration c where
  input   :: c -> PortInShow
  startSt :: c -> SysStateShow

instance Configuration Config where
  input   = PortInShow   . input'
  startSt = SysStateShow . startSt'
+4

behzad.nouri , , . :

class Configuration c where
  input :: (PortIn pin, Show pin) => c -> pin
  startSt :: (SysState st, Show st) => c -> st

, input

input :: (Configuration c, PortIn pin, Show pin) => c -> pin

, , , input , c pin input, c Configuration pin PortIn Show. ( : even :: Integral a => a -> Bool , even , Integral, fromInteger :: Num a => Integer -> a , fromInteger , Num.)

, input Configuration Config , pin, PortIn Show. input = input' pin. . ( , pin " rigit", , , , "" .)

, Gurkenglas: Config .

+4

Source: https://habr.com/ru/post/1665438/


All Articles