11

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

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

4

3 に答える 3

13

について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 TrueなりLeafCon Trueます。しかし、それは許可されていません。なぜなら、の型定義は次のようにLeafConType述べているからです。

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

したがってLeafConType Bool、引数の型は、だけでなく、でLeafConなければなりません。そして、それがコンパイルエラーの意味です。と同じにすることはできません。あなたは次のように述べています。(Bool, Int, Int)Boola(a, Int, Int)

i未満で計算したいn

これは、とのデフォルト値が必要になることを意味します。そうしないin、を定義できなくなります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 afLeafConType b bba

  とにかく、このタイプの計算はモナドとして表現できますか?

于 2009-11-22T18:17:03.323 に答える
7

指定した関数で、次の要件を満たすタイプを満たし>>=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
于 2009-11-22T18:16:52.943 に答える
4

モナドに何をさせたいかについての説明から判断すると、次のようなものが必要だと思います。

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)

私はこれをかなり早く一緒に投げました、それはかなり醜いです、そして私はそれがモナドの法則のいずれかに準拠しているかどうかを確認していませんので、あなたの危険で使用してください!:)

于 2009-11-23T12:16:46.073 に答える