我正在尝试编写一个相当简单的处理器模拟器,并试图将实际处理器与其内存接口分开。例如,旧的TRS-80具有12K的ROM,并且可以配置总共16,32或48K的总RAM。我对内存系统的初步想法是一个类型类:
class MemorySystem memInternals addrType wordType where
-- | General memory fetch. This always returns a 'wordType' value,
-- even if the system's memory internals are byte addressable.
mfetch :: addrType -- ^ The address from which the instruction will be fetched
-> memInternals -- ^ The memory system
-> wordType -- ^ The fetched word
-- | Fetch a block of words from the memory system
mfetchN :: ( Unbox wordType
) =>
addrType -- ^ The address from which the instruction will be fetched
-> Int -- ^ Number of words to fetch
-> memInternals -- ^ The memory system
-> Vector wordType -- ^ The words fetched
澄清:MemorySystem
的要点是允许指令解码器(例如,在TRS-80的情况下为Z80指令解码器)独立于其存储器接口操作,使得所有解码器都需要做为下一条指令及其操作数调用mfetch
。因此,memInternals
是一种类型,它实现了由类型类函数部分指定的内存系统的接口。
在允许addrType
为多态的同时限制wordType
和memInterals
的最佳方式是什么,即允许memInternals
表示不同的内存配置。我发现自己在上下文中添加了上下文:
foo :: ( MemorySystem memSys Word16 Word8) =>
-> memSys
-> Word16
-> Word16
bar :: ( MemorySystem memSys Word16 Word8) =>
-> memSys
-> Word16
-> Word8
bar mem pc = ...
-- bar calls foo -> rigid type variable error...
导致ghc中出现许多严格的类型变量错误。
是否有更好的方法来表达导致MemorySystem
中多态性的“正确类型”的memInternals
,以便可以正确表示一系列内存接口(并通过类型进行操作)班级或家庭)?
答案 0 :(得分:1)
要扩展我的评论,您可以尝试使用关联的类型系列。但看起来您的当前用例很好地由数据类型而不是类型类提供:
{-# LANGUAGE TypeFamilies, RankNTypes #-}
import Data.Vector.Unboxed
class MemorySystem memInternals where
type AddrType memInternals
type WordType memInternals
mfetch :: memInternals
-> AddrType memInternals
-> AddrType wordType
mfetchN :: Unbox wordType
=> memInternals
-> AddrType memInternals
-> Int
-> Vector wordType
-- The record type may be more flexible and appropriate here
data MemorySystem addrType wordType = MemorySystem {
mfetch :: addrType -> wordType
, mfetchN :: Unbox wordType => addrType -> Int -> Vector wordType
}
请参阅类型类如何仅包含仅将类型参数memInternals
作为第一个参数的函数?这似乎等同于记录方法。
答案 1 :(得分:0)
记录方法确实最有效,至少是为了正确分离关注点。这对我有用:
data (Unbox wordType) => MemorySystem addrType wordType memSys =
MemorySystem
{ _mfetch :: addrType -> wordType
, _ mfetchN :: addrType -> Int -> Vector wordType
, _memInternals = memSys
}
(请注意memInternals
可以在mfetch
和mfetchN
内访问,因此无需将其复制为这两个功能的参数。)然后可以创建镜头此记录,例如,使用Control.Lens
和makeLenses
。它还允许定义类型:
import Data.Word
import Data.Int
type Z80addr = Word16
type Z80word = Word8
type Z80memory memConfig = MemorySystem Z80addr Z80word memConfig
允许多态内存配置。非常感谢克里斯提出的建议 - 我不确定为什么我会在类型系列方面围绕着众所周知的轴思考。