I am updating some code I have. I noticed a lot of repeated code, so I took that as a good sign that some abstraction was needed.
I have several functions that transition a State from one to another. The code to execute the transition is identical for every file.
This:
runOneTest :: Config -> Signal TestResult
runOneTest config = TestResult config <$> result
where
result = topEntity startingState inputSignal
startingState = startS config
inputSignal = signal $ input config
What is not identical are the values in the Config Type or the TestResult.
data TestResult = TestResult { initConfig :: Config
, endSt :: St
}deriving (Eq)
data Config = Config { input :: PIn
, startS :: St
}deriving (Eq)
More specifically the values that are different are the St(State) and the PIn(PortsIn). Those types can have different values attached.
Example:
data PIn = PIn { _clk :: Bit
, _reset :: Bool
, _start :: Bool
, _stop :: Bool
}
vs
data PIn = PIn { _in_1 :: Bit
, _clk :: Bit
, _reset :: Bool
}
I was trying to do that with classes but I am running into problems.
Current:
--------------------------------------------------------------------------------
-- 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'
The type of errors I am getting are:
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'
Original Full Source: https://github.com/LambdaScientist/CLaSH-by-example/tree/master
Note: I looked answers to this question, but I did not find a good enough answer.