2016-10-26 24 views
1

以下のようなデータ型がBlahですが、のタイプのため、Functor、Applicative、Monadを自動的に派生できないため、です。だから私は手動で行う必要がありますが、私はどのようにわからない。私は((->) a)のインスタンスからインスピレーションを得ようとしましたが、私はMonadのインスタンスを理解できません。関数型のApplicativeとMonadのインスタンス?

newtype Blah a = Blah (String -> a) -- deriving (Functor, Applicative, Monad) 

-- this seems right 
instance Functor Blah where 
    fmap f (Blah g) = Blah (f . g) 

instance Applicative Blah where 
    pure = Blah . const 
    -- This is right, right? 
    (<*>) (Blah f) (Blah g) = Blah $ \x -> f x (g x) 

instance Monad Blah where 
    return = pure 

    -- I'm not having any luck here. 
    (>>=) a b = Blah $ \c -> _ 

編集:誰かがこれを別のものと重複してマークしましたが、私はその回答をどこから得るのか分かりません。 newtypeラッパーは、これを困難にしました。私は(->) aの前にMonadのインスタンスを調べましたが、私はこの質問を書いていましたが、答えの体操は私が必要なものです。

+1

なぜこれがマークダウンされていますか?それは完全に良い質問のようです。 –

+0

[Monadのインスタンスの使い方( - >)と混乱について( - >)]の可能な複製(http://stackoverflow.com/questions/5310203/how-to-use-instances-of-monad-and-混乱について) – Cactus

答えて

3

どの程度

Blah f >>= g = Blah $ \s -> 
    let Blah h = g $ f s in h s 
+0

私が探していたものとまったく同じです。ありがとう! –

+4

これは 'Reader String'モナドです – pat

+0

私はそこにまさにこれの良い例があることを知っていましたが、私はそれを考えることができませんでした。 –

2

これらのインスタンスはderiveです。 GeneralizedNewtypeDerivingフラグをオンにするだけで、GHCはラップされたタイプのインスタンスを単純に再利用できます。

{-# LANGUAGE GeneralizedNewtypeDeriving #-} 

newtype Blah a = Blah (String -> a) deriving (Functor, Applicative, Monad) 
+0

私が元の投稿で言ったように、私は導出を使うことはできません。これは私の実際のプログラムの型にクラスの制約があるためです。それはまた新しいタイプでもありません。 –

+6

その場合は、_actual_コードをご記入ください。 –

+0

実際のタイプは本当に大きく、複雑すぎるので、ここに入れても数時間、あるいはそれ以外の日には答えられません。私はちょうどこの単純なコードを妥当な時間内に回答して、残りの部分を待っているのではなく、自分のプログラムで作業しています。 –

1

は、ここでは、型指定された穴を使用して、この自分自身を導くことができる方法です。あなたのコードから始めて、少し名前を変更:

instance Monad Blah where 
    return = pure 
    f >>= g = Blah $ \s -> _ 

あなたはこのようなメッセージが表示されます:

Found hole ‘_’ with type: b 
Relevant bindings include 
    s :: String 
    g :: a -> Blah b 
    f :: Blah a 

だから我々はBlah aString与えられ、bを生成する必要がある、とa -> Blah b 。まあ、我々はすでにパターンマッチングとBlahに関数を適用することによって、Blah aStringからaを生成する方法を知っている:

Blah f >>= g = Blah $ \s -> let h = f s in _ 
------      ----------- 

は今我々が得る:

Found hole ‘_’ with type: b 
Relevant bindings include 
    h :: a 
    s :: String 
    g :: a -> Blah b 
    f :: String -> a 

だから我々は持っています我々はBlah bを取得するためにgに与えることができますa、及びその上のパターンマッチングは私たちにString -> bを与える:

Blah f >>= g = Blah $ \s -> let Blah h = g (f s) in _ 
           ---------------- 

今我々が得る:

Found hole ‘_’ with type: b 
Relevant bindings include 
    h :: String -> b 
    s :: String 
    g :: a -> Blah b 
    f :: String -> a 

だから我々はbを必要とし、我々はStringString -> bを持っています。それは簡単です:

Blah f >>= g = Blah $ \s -> let Blah h = g (f s) in h s 
                --- 

あなたが行く、正しい実装は、種類によって導かれます。 Blahを「実行」するヘルパー関数を定義すると、より明確になる場合があります。

newtype Blah a = Blah { runBlah :: String -> a } 
-- or: 
runBlah :: Blah a -> String -> a 
runBlah (Blah f) = f 

instance Monad Blah where 
    f >>= g = Blah $ \s -> runBlah (g (runBlah f s)) s 
関連する問題