質問

スタンダードという考え方は、 Monad クラスに欠陥があるため、実際には拡張する必要がある Functor または Pointed 浮遊している。

私はそれが正しいことであるとは必ずしも主張しませんが、ある人がそれを行おうとしていたと仮定してください。

import Prelude hiding (Monad(..))

class Functor m => Monad m where
    return :: a -> m a
    join :: m (m a) -> m a
    join = (>>= id)
    (>>=) :: m a -> (a -> m b) -> m b
    a >>= t = join (fmap t a)
    (>>) :: m a -> m b -> m b
    a >> b = a >>= const b

ここまではうまくいきましたが、do 記法を使用しようとすると次のようになります。

whileM :: Monad m => m Bool -> m ()
whileM iteration = do
    done <- iteration
    if done
        then return ()
        else whileM iteration

コンパイラは次のように不平を言います。

Could not deduce (base:GHC.Base.Monad m) from the context (Monad m)

質問:

do 記法は次の場合にのみ機能しますか base:GHC.Base.Monad?代替手段で動作させる方法はありますか Monad クラス?

追加のコンテキスト:

本当にやりたいのは交換です base:Control.Arrow.Arrow 「一般化された」 Arrow クラス:

{-# LANGUAGE TypeFamilies #-}

class Category a => Arrow a where
    type Pair a :: * -> * -> *
    arr :: (b -> c) -> a b c
    first :: a b c -> a (Pair a b d) (Pair a c d)
    second :: a b c -> a (Pair a d b) (Pair a d c)
    (***) :: a b c -> a b' c' -> a (Pair a b b') (Pair a c c')
    (&&&) :: a b c -> a b c' -> a b (Pair a c c')

そして、 Arrowのプロシージャ表記と私の Arrow class ですが、上記の do 表記の例のように失敗します。 Monad.

ほとんど使います Either 私のペア型コンストラクターとしてではなく、 (,) 現在と同様の型コンストラクター Arrow クラス。これにより、私のおもちゃの RTS ゲームのコードを作成できるようになるかもしれません (cabal install DefendTheKind)ずっときれいです。

役に立ちましたか?

解決

を使用する必要があります。 NoImplicitPrelude 拡張機能 完全な再バインド可能な構文については、 do そして proc. 。その場合、特に以下のものが得られます。

「Do」表記は、スコープ内にある関数 (>>=)、(>>)、fail を使用して変換されます (Prelude バージョンではありません)。リスト内包表記、mdo (セクション7.3.6「再帰的な do 表記」)、および並列配列内包表記は影響を受けません。

否定、等価、リテラル値などの処理を微調整することもできます。コードを難読化する素晴らしい方法です。

追記-- 再バインドする場合は、 do 構文、 sigfpe が「パラメータ化モナド」と呼ぶもの とても楽しいです。同じアイデアは以下でも利用できます category-extrasControl.Monad.Indexed. 。そして、はい、型署名が大幅に異なるにもかかわらず、再バインド可能な構文で動作します。

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