簡體   English   中英

將 Task[Either] 和 IO[Either] 表示為包含 tryCatch 的單個 monad?

[英]Represent Task[Either] and IO[Either] as a single monad that includes tryCatch?

有沒有辦法將 IOEither 和 TaskEither 表示為一個也包括tryCatch的 Monad?

我目前將在 HTTP 上使用 API,因此使用 TaskEither 是有意義的,但預計此代碼將“離家更近”遷移,此時將其IOEither是有意義的。 所以我想寫一個無標簽風格的消費者界面

interface EngineRepository<M extends URIS2> {
  calculateNumber: (i:SomeData) => Kind2<M, DomainError, number>
}

const getRepo = <M>(m:M extends URIS2):EngineRepository<M> => ({
  calculateNumber: someCalculation(m)()
})

const calculateNumber = <M>(m:M extends URIS2) => flow(/* M.chain, M.map, etc. works great! */)

到目前為止一切都很好,但是,雖然有一個用於 Option、Either、 tryCatch 、IOEither 等的 tryCatch,但我可以說它不是任何接口的一部分。 所以我正在嘗試創建自己的:

interface Tryable<M extends URIS2> extends Monad2<M> {
  tryCatch: <E,A>(f:Lazy<A>, onError: (reason:unknown) => E) => Kind2<M, E, A>
}

const calculateNumber = <M>(m:M extends URIS2) => 
  flow(/* M.tryCatch works great now! */)

這里的問題是IOError是同步的,所以f:Lazy<A>很好, TaskEither是異步的,所以它需要f:Lazy<Promise<A>>代替。

有沒有更好的方法來解決這個問題,或者這是不可能的? 我是否需要始終使用 TaskEither,然后添加一個將 IOEither 轉換為 TaskEither 並放棄無標記決賽的步驟?

我有一個臨時的解決方案,感覺很hacky:

interface Tryable<M extends URIS2, ThunkType extends 'Task'|'IO'> extends MonadIO2<M> {
  tryCatch: <E, A>(f:Kind<ThunkType, A>, onError: (e:unknown)=>E) => Kind2<M, E, A>
}

const te: Tryable<'TaskEither', 'Task'> = { ...TE.taskEither, tryCatch: TE.tryCatch}
const ioe: Tryable<'IOEither', 'IO'> = { ...IOE.ioEither, tryCatch: IOE.tryCatch}

pipe(te.tryCatch(()=>Promise.resolve(5),()=>'error'), te.map(num=>`${num}`)) // TaskEither<'error',string>

pipe(ioe.tryCatch(()=>5,()=>'error'), ioe.map(num => `${num}`)) // IOEither<'error',string>

它有效,但我不喜歡它結合 monads 和 thunk 類型,原因有兩個:

  1. 如果我們為Option實現Tryable ,則 thunk 類型仍然是IO 對於Either和其他人也是如此。 就是它開始感覺 hacky 的地方,將OptionEitherIO緊密耦合!

  2. 這只是一個幸運的巧合,這要歸功於鴨子類型Lazy<A>IO<A>的類型相同,而Lazy<Promise<A>>Task<A>的類型相同。 如果這要改變,這個解決方案就行不通了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM