質問

私は自分のモナドを作成したいです。これは私が書いたものです。

data LeafConType a = LeafCon (a,Int,Int)

instance Monad (LeafConType ) where
return = LeafCon 
lc@(LeafCon (t,i,n)) >>= f = if i>=n
                                then lc
                                else f (t,i,n)

しかし、これはいけない仕事。 GHCは述べています:

leafcon.hs:26:1:
    Occurs check: cannot construct the infinite type: a = (a, Int, Int)
    When generalising the type(s) for `return'
    In the instance declaration for `Monad LeafConType'

leafcon.hs:27:1:
    Occurs check: cannot construct the infinite type: a = (a, Int, Int)
    When generalising the type(s) for `>>='
    In the instance declaration for `Monad LeafConType'

をいただきました!それと間違っている?

<時間> 私はiがnよりも小さいながら計算を行いたいです。 nは、私はこれが正しいを行う方法をまだ知らないことで、定数でなければなりません。それはたぶん、国家とのいくつかの組み合わせでなければなりません。あなたはいくつかのアドバイスは私と一緒にそれを共有すること自由に感じている場合:P

役に立ちましたか?

解決

returnについて:

Prelude> :t return
return :: (Monad m) => a -> m a 

だから、のreturnはタイプaの引数を取り、型m aのリターンの何か。この場合、mLeafConTypeので、LeafConType aが返されます。

今、私たちはTrueを渡したとします。その後a = Boolは、その戻り値の型はLeafConType Boolでなければなりません。ただし、ユーザーが定義します:

return = LeafCon
だから、return TrueLeafCon Trueになります。

そのLeafConType状態の型定義ので、しかし、許可されていないこと
data LeafConType a = LeafCon (a, Int, Int)

だから、LeafConType BoolためLeafConへの引数は、型(Bool, Int, Int)だけでなく、Boolを持っている必要があります。 a(a, Int, Int)と同じにすることはできません。そして、それはどのようなコンパイルエラー手段です。あなたの状態:

  

私はinよりも小さいながら計算を行いたい。

それ以外の場合はiを定義することは不可能となりますため、あなたが、nreturnためにいくつかのデフォルト値が必要になりますことを、この手段。それらの両方は、デフォルトではゼロである場合は、定義することができます:

return a = LeafCon (a, 0, 0)

(>>=)について:

Prelude> :t (>>=)
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b

さて、あなたの実装を見て(わずかに異なる表記、同じ考え方):

lc@(LeafCon (t, i, n)) >>= f | i >= n    = lc 
                             | otherwise = f t
私たちはここを参照してください何を、lcのときi >= nを返されることです。 lcのいずれかのLeafConType aため、型fの値を返すことが機能している間しかしLeafConType bは、タイプbです。その結果、そのbaに等しくなく、したがって、これらの型が一致しない可能性があります。結論として、あなたが真剣に自分自身に一つの質問を依頼する必要があります:

?計算のこのタイプは、とにかくモナドのように表すことができます。

他のヒント

あなたは>>=returnのために指定された機能は、Monadによって必要な種類を満たしていない。

return :: a -> LeafConType a

タグの宣言を考えます
return = LeafCon

あなたが関数に互換性のない型を与える

return :: (a, Int, Int) -> LeafConType a

return 42ようなステートメントは、したがって、あなたのモナドでは不可能であろう。

私はあなたのモナドがすべてで何をすべきか理解していません。 まず、モナド作業、シンプルで見てみましょう!

instance Monad [] where
    (>>=) = concatMap
    return a = [a]

instance Monad Maybe where
    return = Just
    (Just x) >>= f = f x
    Nothing >>= f = Nothing
あなたのモナドが何をしたいのかをご説明から判断すると、私はあなたが何かをしたいと思います。このようなビットます:

data LeafConType a = LeafCon { runLeafCon' :: Int -> Int -> (Maybe a, Int, Int) }

runLeafCon :: Int -> Int -> LeafConType a -> Maybe a
runLeafCon i n lc = let (t, _, _) = runLeafCon' lc i n in t

getI :: LeafConType Int
getI = LeafCon $ \i n -> (Just i, i, n)

getN :: LeafConType Int
getN = LeafCon $ \i n -> (Just n, i, n)

setI :: Int -> LeafConType ()
setI i = LeafCon $ \_ n -> (Just (), i, n)

setN :: Int -> LeafConType ()
setN n = LeafCon $ \i _ -> (Just (), i, n)

instance Monad LeafConType where
    return t = LeafCon $ \i n -> if (i < n) 
                                 then (Just t, i, n) 
                                 else (Nothing, i, n)

    (LeafCon k) >>= f = 
        LeafCon $ \i n -> 
            let (t, i', n') = k i n
            in case t of
                 Nothing -> (Nothing, i', n')
                 (Just t') -> if (i' < n')
                              then runLeafCon' (f t') i' n'
                              else (Nothing, i, n)


example :: Int -> LeafConType ((), Int)
example x = do 
  i <- getI
  m <- setI (i + x)
  return (m, i + x)

いくつかの例:

*Main> runLeafCon 2 10 $ example 4
Just ((),6)
*Main> runLeafCon 2 10 $ example 8
Nothing
*Main> runLeafCon 2 10 $ example 7
Just ((),9)
私はかなり迅速に、それはかなり醜い一緒にこれを投げた、と私はそれがあなたの危険を覚悟で使用して、モナドの法律のいずれかに従うかどうかをチェックしていません! :)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top