Eff
에 대한 인스턴스를 만들려고하기 때문에 유형에 행을 포함해야하므로 약간의 문제가 있습니다.하지만 아마 알았 듯이 컴파일러는이 경우 인스턴스 헤드에 대해 불평합니다.
하나의 옵션은 newtype
사용하는 것입니다
import Prelude
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Exception (EXCEPTION)
import Data.Tuple (Tuple)
import Node.FS (FS)
import Node.Path (FilePath)
type FileType = String
class (Monad m) <= MonadFileSystem m where
cd :: FilePath -> m Unit
ls :: m (Array (Tuple FilePath FileType))
cat :: Array FilePath -> m String
newtype FSEff eff a = FSEff (Eff (fs :: FS, err :: EXCEPTION | eff) a)
runFSEff :: forall eff a. FSEff eff a -> Eff (fs :: FS, err :: EXCEPTION | eff) a
runFSEff (FSEff fse) = fse
derive newtype instance functorFSEff :: Functor (FSEff eff)
derive newtype instance applyFSEff :: Apply (FSEff eff)
derive newtype instance applicativeFSEff :: Applicative (FSEff eff)
derive newtype instance bindFSEff :: Bind (FSEff eff)
derive newtype instance monadFSEff :: Monad (FSEff eff)
instance monadFileSystemFSEff :: MonadFileSystem (FSEff eff) where
cd _ = pure unit
ls = pure []
cat _ = pure "meow"
을하지만 대신 평등 제약 같은 행을 지정할 수있는 기능적인 종속성을 사용하여 수행 할 수있는 몇 가지 속임수도 있습니다. 이 컴파일,하지만 난 아직 실제,이 기술을 사용하여 시도하지 않은 그래서 큰 문맥에서 확실히 작동하도록 보증 할 수 없습니다.
import Prelude
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Exception (EXCEPTION)
import Data.Tuple (Tuple)
import Node.FS (FS)
import Node.Path (FilePath)
type FileType = String
class (Monad m) <= MonadFileSystem m where
cd :: FilePath -> m Unit
ls :: m (Array (Tuple FilePath FileType))
cat :: Array FilePath -> m String
instance monadFileSystemEff :: EffectRowEquals r (fs :: FS, err :: EXCEPTION | eff) => MonadFileSystem (Eff r) where
cd _ = pure unit
ls = pure []
cat _ = pure "meow"
-- This should probably go in `purescript-type-equality`:
class EffectRowEquals (a ∷ # !) (b ∷ # !) | a → b, b → a where
toER ∷ ∀ r. r a → r b
fromER ∷ ∀ r. r b → r a
instance reflER ∷ EffectRowEquals r r where
toER er = er
fromER er = er
정말 자세한 답변을 많이 고마워. 전작은 부작용 만있는 상황에서도 효과가 있습니다. 여러 상황에서 필요한 현재 작업 디렉토리와 같은 컨텍스트가있는 방식으로 작성하는 데 여전히 어려움이 있습니다. 나는 FakeFS 인스턴스의 Zipper 예제와 비슷한 방식으로 해킹을 시도했지만 좋은 newtype 파생물을 모두 파기합니다. 두 번째 솔루션은 정말 아름답고 표현력이 뛰어나지 만, AbstractFileSystem과 함께 배치하지 않으면 고아 인스턴스 오류가 발생하는 것으로 보입니까? –
'MonadFileSystem'과 함께'MonadFileSystem'과 함께 고아 오류를 피할 필요가 있다는 것은 사실입니다 (다른 고아가 아닌 곳은 'Eff'가있는 모듈에 있지만 분명히 옵션이 아닙니다!). 그러나 당신의 후속 질문을 감안할 때, 어쨌든 cwd 등을 유지하기 위해'Eff' 주위에'StateT'가 필요할 것 같아요 .- 만약'newtype' 라우트를 가야한다면 고아 문제를 피할 수있을 것입니다. 너무. –