2012-12-13 66 views
1

我想写一个相当直接的处理器模拟器,并试图将实际处理器从其存储器接口分开。例如,旧的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是一种实现与由类型类函数部分指定的内存系统的接口的类型。

限制addrTypewordType的最佳方式是什么,同时允许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中出现很多刚性类型的可变错误。

有没有更好的方式来表达导致memInternals中多态性的“正确类型”的MemorySystem,以便可以正确表示一系列的存储器接口(并通过类型类或系列来执行操作)?

+0

问题不清楚你想要什么样的多态性?另外你刚性类型变量的问题不是很清楚。也许你应该添加更多的代码和错误。 – Satvik

+0

@ user1902082您可能正在寻找函数依赖关系(将您的类更改为'class MemorySystem memInternals addrType wordType | memInternals - > addrType wordType'),以便您的地址和单词类型由'memInternals'唯一确定,但尚不清楚“重新寻找 – jberryman

+0

@jberryman:这部分是我要找的。还有另外一个部分,它可以有效地在各种内存配置中实现'memInternals'的多态性,例如Z80指令解码器只需调用mfetch来获得下一条指令或操作码。但是,使用'MemorySystem'作为约束会导致刚性类型变量问题。 也许我正在寻找词法类型变量? –

回答

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

记录方法的唯一缺点是需要包装或嵌入内存系统内部(例如,Z80的内存与更具体的TRS-80版本的通用模型),但它看起来可行。 OTOH,记录意味着镜头有趣的事情(我个人喜欢Control.Lens)。 –

0

记录方法的确效果最好,至少为了正确分离关注点。下面是我的什么作品:

data (Unbox wordType) => MemorySystem addrType wordType memSys = 
    MemorySystem 
    { _mfetch :: addrType -> wordType 
    , _ mfetchN :: addrType -> Int -> Vector wordType 
    , _memInternals = memSys 
    } 

(请注意,memInternals可以从内部mfetchmfetchN进行访问,因此没有必要重复它作为参数传递给这两个功能。)它当时可能为这个纪录创造镜头例如使用Control.LensmakeLenses。它还允许定义类型,如:

import Data.Word 
import Data.Int 

type Z80addr = Word16 
type Z80word = Word8 
type Z80memory memConfig = MemorySystem Z80addr Z80word memConfig 

允许多态内存配置。非常感谢克里斯提出的建议 - 我不确定为什么我会按照家庭类型考虑谚语。