I think this way of emulation does not always work e.g. not as expressive as HKT.
Just from my humble and shallow understanding of FP and CT.
When I used your Swift HKT emulation idea in re-writing Haskell Parsec in Swift following ideas from Parsec Paper.
I encounter a difficulty to implement the following function
runParsecT :: Monad m => ParsecT s u m a -> State s u -> m (Consumed (m (Reply s u a)))
into
public func runParsecT <S, U, A, M:Monad>
(_ p: Parser<S, U, A>, _ s: ParserState<S, U>, _ dummy: M) ->
HKT_TypeParameter_Binder<M.HKTValueKeeper, ParserResult<HKT_TypeParameter_Binder<M.HKTValueKeeper, Reply<S, U, A>>>> {
switch p.unParser(s) {
case .consumed(let reply):
switch reply {
case let .ok(x, s_, e):
let ok: Reply<S, U, A> = Reply<S, U, A>.ok(x, s_, e)
// mok: HKT_TypeParameter_Binder<M.HKTValueKeeper, M.A>
// M.A == Reply<S, U, A>
let mok = M.return(ok as! M.A)
// cok : ParserResult<HKT_TypeParameter_Binder<M.HKTValueKeeper, M.A>>
let cok = ParserResult.consumed(mok)
// mcok: HKT_TypeParameter_Binder<M.HKTValueKeeper, M.A>
// M.A = ParserResult<HKT_TypeParameter_Binder<M.HKTValueKeeper, M.A>>
let mcok = M.return(cok as! M.A)
// Error: Cannot convert
// HKT_TypeParameter_Binder<M.HKTValueKeeper, M.A>
// into
// HKT_TypeParameter_Binder<M.HKTValueKeeper, ParserResult<HKT_TypeParameter_Binder<M.HKTValueKeeper, Reply<S, U, A>>>>
return mcok
case let .error(e): fatalError("left to implement")
}
case .empty(let reply): fatalError("left to implement")
}
}
As what I see, The M.A (the wrapped type in monad) cannot be two different type.
Because in Swift, every generic type should be deducible to a concrete type. Then when parsing this function, the type for M should be a concrete type, therefore M.HKTValueKeeper and M.A are concrete types as well.
So M.A cannot represent different types in the same context.
Is there something wrong in my reasoning. Please let me know.
By the way, actually, I love FP and CT, really looking forward that Swift can fully support FP and CT sooner or latter.