我正在用Haskell编写markov链生成器,使用加权列表随机选择元素。测试配置时,出现错误“无法将类型'Item a0'与'[Item [Char]]'相匹配”。我怀疑这与以下事实有关:Item
已参数化并且类型检查没有意识到configContinuations
中的元素具有正确的类型(因此a0
与[Char]
相对。
在添加addElement :: forall a. Ord a => Maybe a -> a -> Config a -> Config a
量词之前,我具有签名forall a
的函数也存在类似的问题。
但是,如果我将值检查为:config ^? (configContinuationsL . at "AA" . _Just . itemFreqL) `shouldBe` Just 1
,则不知道该怎么做。
下面是Config
,Item
,Frequency
和用于操作它们的镜头的定义。
data Frequency a = Frequency Int a
deriving (Show, Read, Eq)
data Config a = Config
{ configStarts :: ![Item a]
, configContinuations :: !(M.Map a [Item a])
} deriving (Show, Read, Eq)
data Item a =
Item (Frequency (Maybe a))
deriving (Show, Read, Eq)
makeLensesFor [ ("configStarts", "configStartsL")
, ("configContinuations", "configContinuationsL")] ''Config
itemFreqL :: Lens' (Item a) Int
itemFreqL = lens (\(Item (Frequency n _)) -> n)
(\(Item (Frequency _ a)) n -> (Item (Frequency n a)))
我应该更改什么,以便强制类型匹配?
编辑:完整的错误消息
• Couldn't match type ‘Item a0’ with ‘[Item [Char]]’
Expected type: (Int
-> Data.Functor.Const.Const (Data.Monoid.First Int) Int)
-> [Item [Char]]
-> Data.Functor.Const.Const (Data.Monoid.First Int) [Item [Char]]
Actual type: (Int
-> Data.Functor.Const.Const (Data.Monoid.First Int) Int)
-> Item a0
-> Data.Functor.Const.Const (Data.Monoid.First Int) (Item a0)
• In the second argument of ‘(.)’, namely ‘itemFreqL’
In the second argument of ‘(.)’, namely ‘_Just . itemFreqL’
In the second argument of ‘(.)’, namely
‘at "AA" . _Just . itemFreqL’
config ^? (configContinuationsL . at "AA" . _Just . itemFreqL) `shouldBe` Just 1
以及我的测试规范:
spec :: Spec
spec = do
describe "Markov chain configuration" $ do
it "Adding new starting element to empty configuration creates item with frequency of 1" $ do
let config = addElement Nothing "AA" emptyConfig
config ^? (configStartsL . ix 0 . itemFreqL) `shouldBe` Just 1
config ^? (configStartsL . ix 0 . itemItemL . _Just) `shouldBe` Just "AA"
it "Adding same element twice to empty configuration creates item with frequency of 2" $ do
let config = addElement Nothing "AA" $
addElement Nothing "AA" emptyConfig
config ^? (configStartsL . ix 0 . itemFreqL) `shouldBe` Just 2
config ^? (configStartsL . ix 0 . itemItemL . _Just) `shouldBe` Just "AA"
it "Adding new continuation creates item with frequency of 1" $ do
let config = addElement (Just "AA") "BB" $
addElement Nothing "AA" emptyConfig
config ^? (configContinuationsL . at "AA" . _Just . itemFreqL) `shouldBe` Just 1