7

seperateFuncs私はそのような機能を持っています

seperateFuncs :: [a -> b] -> (a -> [b])
seperateFuncs xs = \x -> map ($ x) xs

逆が存在するかどうか、つまり機能があるかどうか疑問に思っていました

joinFuncs :: (a -> [b]) -> [a -> b]

私はそうは思わない (主にリストは固定長ではないため) が、おそらく私が間違っていることが証明されるだろう. f問題は、関数 :: (a -> fb) -> f (a -> b) を持つデータ型があるかどうかです。

4

5 に答える 5

7

あなたはかなりきれいに一般化seperateFuncsすることができますApplicative(または):Monad

seperateFuncs :: (Applicative f) => f (a -> b) -> (a -> f b)
seperateFuncs f x = f <*> pure x

ポイントフリースタイルで書かれているseperateFuncs = ((. pure) . (<*>))ので、基本的には、ポイントフリースタイルでunap . (. extract)書く場合は次の定義を与えます。

joinFuncs :: (Unapplicative f) => (a -> f b) -> f (a -> b)
joinFuncs f = unap f (\ g -> f (extract g))

ここで私は次のように定義Unapplictaiveします:

class Functor f => Unapplicactive f where
    extract  :: f a -> a
    unap     :: (f a -> f b) -> f (a -> b)

leftaroundaboutで指定された定義を取得するには、次のインスタンスを指定できます。

instance Unapplicative [] where
    extract = head
    unap f = [\a -> f [a] !! i | i <- [0..]]

instance Unapplicative ((->) c) where
    extract f = f undefined
    unap f = \x y -> f (const y) x

のようなものではないものに「便利な」機能f :: (f a -> f b) -> f (a -> b)を思いつくのは難しいと思います。f(->)

于 2012-12-07T17:45:10.313 に答える
4

まず第一に、この関数をブルートフォースすることができます:

joinFuncs f = [\x -> f x !! i | i<-[0..]]

しかし、これは明らかに厄介です。結果のリストは常に無限ですが、ith 要素の評価はxif でしか成功しませんlength(f x) > i

「本当の」解決策を与えるために

f問題は、機能を持つデータ型がある:: (a -> f b) -> f (a -> b)かどうかです。

を検討してください(->)c。これで、あなたの署名は(a -> (c->b)) -> (c->(a->b))または同等(a -> c -> b) -> c -> a -> bに読み取られますflip

seperateFuncsもちろん、これは、この型に対して同じシグネチャを持っているため、ちょっとしたことではありません...

于 2012-12-07T15:26:45.537 に答える
3

「関数 :: (a -> fb) -> f (a -> b) を持つデータ型 f はありますか?」

実際、この関数のさらに一般的なバージョンがTraversable型クラスにあり、交換可能なファンクターを扱います。

class (Functor t, Foldable t) => Traversable t where

  ... 

  sequenceA :: Applicative f => t (f b) -> f (t b)

これはあなたの機能にどのように関連していますか? あなたのタイプから始めて、1つのタイプ置換で、回復しsequenceAます:

  1. (a -> f b) -> f (a -> b) ==> let t = (->) a
  2. t (f b) -> f (t b)

ただし、この型にはtTraversable でなければならないという制約があり、 には Traversable インスタンスがありません(->) a。つまり、この操作は一般に関数では実行できません。「他の方向」に注意してください --f (a -> b) -> (a -> f b)すべての関数とすべての Applicative で問題なく動作しますf

于 2012-12-07T18:10:37.590 に答える
3

私は最近、あなたの質問に非常に似た質問に還元される問題についてかなり考えなければなりませんでした. これが私が見つけた一般化です。

まず、これを行うのは簡単です (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 つのパラメーターを持つ非常に一般的なタイプのモナド アクションですが、 は非常に一般的なタイプです。適切な名前がわからないため、次のように呼び出します「適用可能なアプリケーション」。そして、できないことをできるという事実は、存在できないという事実に結びついています。ApplicativeMonadMonad m => a -> m bApplicative f => f (a -> b)MonadApplicativem2a

だから今、あなたの質問に適用されます:

joinFuncs :: (a -> [b]) -> [a -> b]

同じ "Monad /= Applicative" 引数 (繰り返しますが、強調させてください。完全には理解していません) がここで適用されるべきだと思います。Monad []インスタンスができないことをインスタンスができることがわかっていますApplicative []joinFuncs指定された型で を記述できる場合、結果は何らかの意味で引数[a -> b]と比較して「情報を失う」必要があります。それ以外の場合は と同じであるためです。(そして、「失う」情報とは、の型を持つ関数は逆を持つことができないことを意味し、したがって、関数のいくつかのペア間の区別をなくすことが保証されています。その極端なケースは です。)a -> [b]Applicative []Monad []joinFuncsf, 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これを行うにはある意味で結果を「具体化」する必要があるという興味深い観察結果があることに注意してください。関数/アクションから、ある種のリスト、マップ、またはテーブルに変換します。

于 2012-12-07T19:29:11.710 に答える