Haskell为类型实现不同的行为以增加代码重新生成

时间:2016-12-30 17:24:15

标签: haskell abstraction

我正在更新我的一些代码。我注意到了很多重复的代码,所以我认为这是一个好的迹象,需要一些抽象。

我有几个函数可以将状态从一个状态转换为另一个状态。执行转换的代码对于每个文件都是相同的。

:此:

runOneTest :: Config -> Signal TestResult
runOneTest config = TestResult config <$> result
  where
    result = topEntity startingState inputSignal
    startingState = startS config
    inputSignal   = signal $ input config

Config Type或TestResult中的值不相同。

data TestResult = TestResult { initConfig  :: Config
                             , endSt        :: St
                             }deriving (Eq)

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

更具体地说,不同的值是St(状态)和PIn(PortsIn)。这些类型可以附加不同的值。

示例:

data PIn = PIn { _clk   :: Bit
               , _reset :: Bool
               , _start :: Bool
               , _stop  :: Bool
               }

vs

data PIn = PIn { _in_1 :: Bit
               , _clk  :: Bit
               , _reset :: Bool
               } 

我试图用课程来做这件事,但我遇到了问题。

当前

--------------------------------------------------------------------------------
-- Abstract Area
--------------------------------------------------------------------------------
data TestResult = TestResult { initConfig :: (Transition t) => t
                             , endSt      :: (SysState s) => s
                             }

data Config = Config { input   :: (PortIn p) => p
                     , startSt :: (SysState s) => s
                     }

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

class Transition t where
  runOneTest :: (Transition t) => t -> Signal TestResult

class Result r

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



--------------------------------------------------------------------------------
-- Stuff to define in each file
--------------------------------------------------------------------------------

runOneTest' :: (Transition t) => t -> Signal TestResult
runOneTest' config = signal $ TestResult config st

data PIn = PIn { _clk   :: Bit
               , _reset :: Bool
               , _start :: Bool
               , _stop  :: Bool
               } deriving (Eq, Show)
instance PortIn PIn

data St = St { _cnt_en   :: Bool
             , _count_us :: BitVector 4
             , _stop_d1  :: Bool
             , _stop_d2  :: Bool
             , _count    :: BitVector 4
             } deriving (Eq, Show)
instance SysState St

st :: St
st = St False 0 False False 0

instance Result TestResult

instance Transition Config where
  runOneTest = runOneTest'

我得到的错误类型是:

Couldn't match expected type `t1' with actual type `t'
  `t' is a rigid type variable bound by
      the type signature for
        runOneTest' :: Transition t => t -> Signal TestResult
      at ConvertedClashExamples\ClassExample.hs:50:16
  `t1' is a rigid type variable bound by
       a type expected by the context: Transition t1 => t1
       at ConvertedClashExamples\ClassExample.hs:51:31
Relevant bindings include
  config :: t (bound at ConvertedClashExamples\ClassExample.hs:51:13)
  runOneTest' :: t -> Signal TestResult
    (bound at ConvertedClashExamples\ClassExample.hs:51:1)
In the first argument of `TestResult', namely `config'
In the second argument of `($)', namely `TestResult config st'

原始资料来源: https://github.com/LambdaScientist/CLaSH-by-example/tree/master

注意:我看了这个问题的答案,但我找不到足够好的答案。

0 个答案:

没有答案