0

I'm writing markov chain generator with Haskell, using weighted list for randomly selecting elements. When I'm testing the configuration, I get an error "Couldn't match type ‘Item a0’ with ‘[Item [Char]]’". I suspect this is somehow related to the fact that Item is parametrized and type checked doesn't realize that elements in configContinuations have correct type (hence a0 vs. [Char].

I have function with signature addElement :: forall a. Ord a => Maybe a -> a -> Config a -> Config a that had similar problem, before I added forall a quantifier.

However, if I'm checking value as: config ^? (configContinuationsL . at "AA" . _Just . itemFreqL) `shouldBe` Just 1, I don't know how to do similar thing.

Below are definitions for Config, Item, Frequency and lenses used to operate with them.

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)))

What should I change, so I could force types to match?

Edit: Full error message

• 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

and spec of how I'm testing:

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
Tuukka Turto
  • 145
  • 1
  • 2
  • 7

0 Answers0