質問
私は自分のモナドを作成したいです。これは私が書いたものです。
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
のリターンの何か。この場合、m
はLeafConType
ので、LeafConType a
が返されます。
今、私たちはTrue
を渡したとします。その後a = Bool
は、その戻り値の型はLeafConType Bool
でなければなりません。ただし、ユーザーが定義します:
return = LeafCon
だから、return True
はLeafCon True
になります。
LeafConType
状態の型定義ので、しかし、許可されていないこと
data LeafConType a = LeafCon (a, Int, Int)
だから、LeafConType Bool
ためLeafCon
への引数は、型(Bool, Int, Int)
だけでなく、Bool
を持っている必要があります。 a
が(a, Int, Int)
と同じにすることはできません。そして、それはどのようなコンパイルエラー手段です。あなたの状態:
私は
i
がn
よりも小さいながら計算を行いたい。
それ以外の場合はi
を定義することは不可能となりますため、あなたが、n
とreturn
ためにいくつかのデフォルト値が必要になりますことを、この手段。それらの両方は、デフォルトではゼロである場合は、定義することができます:
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
です。その結果、そのb
がa
に等しくなく、したがって、これらの型が一致しない可能性があります。結論として、あなたが真剣に自分自身に一つの質問を依頼する必要があります:
の ののの
?計算のこのタイプは、とにかくモナドのように表すことができます。他のヒント
あなたは>>=
と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)
私はかなり迅速に、それはかなり醜い一緒にこれを投げた、と私はそれがあなたの危険を覚悟で使用して、モナドの法律のいずれかに従うかどうかをチェックしていません! :)