многозначность не обнаруживает элемент

#haskell #haskell-polysemy

#haskell #haskell-многозначность

Вопрос:

Я пытаюсь написать кучу инструкций с помощью Hspec внутри Sem монады одной многозначности как таковой:

 {-# OPTIONS_GHC -fplugin=Polysemy.Plugin #-}

{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE GADTs               #-}
{-# LANGUAGE KindSignatures      #-}
{-# LANGUAGE LambdaCase          #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RankNTypes          #-}
{-# LANGUAGE TemplateHaskell     #-}
{-# LANGUAGE TypeApplications    #-}
{-# LANGUAGE TypeOperators       #-}

module StorageSpec (main, spec) where

import Test.Hspec

import Storage
import Data.Aeson
import Data.Maybe(fromJust)
import qualified Data.Text as T
import qualified Database.Bloodhound as B
import qualified Database.Bloodhound.Types as B
import GHC.Generics
import Polysemy (Embed, Member, Sem, makeSem, embed, interpret, reinterpret)
import Polysemy.IO
import Polysemy.State


data Storage (d :: *) (m :: * -> *) (a :: *) where
  CreateContainer :: B.IndexName -> B.IndexSettings -> Storage d m Bool

makeSem ''Storage

scenarii :: Member (Storage Book) r => Sem r (SpecWith ())
scenarii = do
  indexCreation <- it "create index should work the first time" . flip shouldBe True
    <$> (createContainer exampleIndex exampleMapping :: Member (Storage Book) r => Sem r Bool)
  return $ indexCreation

data Book = Book { name :: String, entries :: Int } deriving (Eq, Show, Generic, FromJSON, ToJSON)
  

При явном указании Storage Book Member у меня возникает следующая ошибка:

Ambiguous use of effect 'Storage'
      Possible fix:
        add (Member (Storage d1) r1) to the context of
          the type signature
      If you already have the constraint you want, instead
        add a type application to specify
          'd1' directly, or activate polysemy-plugin which
            can usually infer the type correctly.In the second argument of ‘(<$>)’, namely
        ‘(createContainer exampleIndex exampleMapping ::
            Member (Storage Book) r => Sem r Bool)’
      In a stmt of a 'do' block:
        indexCreation <- it "create index should work the first time"
                           . flip shouldBe True
                           <$>
                             (createContainer exampleIndex exampleMapping ::
                                Member (Storage Book) r => Sem r Bool)
      In the expression:
        do indexCreation <- it "create index should work the first time"
                              . flip shouldBe True
                              <$>
                                (createContainer exampleIndex exampleMapping ::
                                   Member (Storage Book) r => Sem r Bool)
           return $ indexCreation
   |
39 |     <$> (createContainer exampleIndex exampleMapping :: Member (Storage Book) r => Sem r Bool)
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  

Я не вижу, что я могу сделать, чтобы помочь проверке типов.

Ответ №1:

Случается, что d действует как фантомный тип в случае CreateContainer , чтобы исправить это, мне пришлось использовать тип application:

 createContainer @Book exampleIndex exampleMapping