私は最近、あなたの質問に非常に似た質問に還元される問題についてかなり考えなければなりませんでした. これが私が見つけた一般化です。
まず、これを行うのは簡単です (Tinctorius が指摘):
f2m :: Functor f => f (a -> b) -> a -> f b
f2m f a = fmap ($a) f
しかし、これを一般的に行うことは不可能です。
m2a :: Monad m => (a -> m b) -> m (a -> b)
これを理解する洞察に満ちた方法の 1 つは、誰かが #haskell irc チャンネルで親切に説明してくれたことですが、関数が存在する場合、 と の間にm2a
違いはないということです。なんで?まあ、私はそれを 100% 守っているわけではありませんが、次のようなものです:は 1 つのパラメーターを持つ非常に一般的なタイプのモナド アクションですが、 は非常に一般的なタイプです。適切な名前がわからないため、次のように呼び出します「適用可能なアプリケーション」。そして、できないことをできるという事実は、存在できないという事実に結びついています。Applicative
Monad
Monad m => a -> m b
Applicative f => f (a -> b)
Monad
Applicative
m2a
だから今、あなたの質問に適用されます:
joinFuncs :: (a -> [b]) -> [a -> b]
同じ "Monad /= Applicative" 引数 (繰り返しますが、強調させてください。完全には理解していません) がここで適用されるべきだと思います。Monad []
インスタンスができないことをインスタンスができることがわかっていますApplicative []
。joinFuncs
指定された型で を記述できる場合、結果は何らかの意味で引数[a -> b]
と比較して「情報を失う」必要があります。それ以外の場合は と同じであるためです。(そして、「失う」情報とは、の型を持つ関数は逆を持つことができないことを意味し、したがって、関数のいくつかのペア間の区別をなくすことが保証されています。その極端なケースは です。)a -> [b]
Applicative []
Monad []
joinFuncs
f, g :: a -> [b]
joinFuncs = undefined
私が見つけm2a
た特別なケースは、これを行うことが可能であるということです:
import Data.Map (Map)
import qualified Data.Map as Map
-- | Enumerate a monadic action within the domain enumerated by the
-- argument list.
boundedM2a :: Monad m => (a -> m b) -> [a] -> m [(a,b)]
boundedM2a f = mapM f'
where f' a = do b <- f a
return (a, b)
-- | The variant that makes a 'Map' is rather useful.
boundedM2a' :: (Monad m, Ord a) => (a -> m b) -> [a] -> m (Map a b)
boundedM2a' f = liftM Map.fromList . boundedM2a f
sを列挙するという要件に加えて、a
これを行うにはある意味で結果を「具体化」する必要があるという興味深い観察結果があることに注意してください。関数/アクションから、ある種のリスト、マップ、またはテーブルに変換します。