2016-04-27 9 views
3

このように動作するListのMonadインスタンスを作ることは可能ですか? [Int]要素を追加するモナドインスタンスをリストする

foo = do 
    [1] 
    [2] 
    [3] 

main = print foo -- prints [1,2,3] 

は、私はすべての配列が同じ型を持つ制約が必要になり、この作業を行います。

+0

'(>>)の型を' m a - > m a - > m a'に変更する方法はありますか? –

+2

実際には '-XRebindableSyntax'を使ってこれを実現できますが、モナドとは関係ありません。 @カルステン、これは答えになるはずです! (実際には、 '1'と' 2'の両方を無視するというより正確です - リストの棘は無視されません!) – leftaroundabout

+4

@VladtheImpalaリストモナドでなければなりませんか?作者のモナドは 'foo = do {tell [1]; tell [2]; tell [3]} '、execwriter foo'を実行した場合、' [1,2,3] 'が返されます。 – bheklilr

答えて

5

あなたはmtlWriterモナドと狂気何もあなたが望む効果を得ることができます。

type AutoList a = Writer [a]() 

foo :: AutoList Int 
foo = do 
    tell [1] 
    tell [2] 
    tell [3] 

toList :: AutoList a -> [a] 
toList = execWriter 

main = print (toList foo) 

しかし、あなたはソートのためだけにリストリテラルとそれを得る-XOverloadedListsでひどいハックを行うことができます。注意すべき点は、各ライン上に型シグネチャを与える必要があるということです。

{-# LANGUAGE OverloadedLists #-} 
{-# LANGUAGE FlexibleContexts #-} 
{-# LANGUAGE FlexibleInstances #-} 
{-# LANGUAGE TypeFamilies #-} 
{-# LANGUAGE GeneralizedNewtypeDeriving #-} 
module AutoList where 

import GHC.Exts 
import Control.Applicative 
import Control.Monad.Writer 

newtype AutoListM a r = AutoListM (Writer [a] r) deriving (Functor, Applicative, Monad) 

type AutoList a = AutoListM a() 

instance IsList (AutoList a) where 
    type Item (AutoList a) = a 
    fromList = AutoListM . tell 
    fromListN n = AutoListM . tell . take n 
    toList (AutoListM w) = execWriter w 


foo :: AutoList Int 
foo = do 
    [1] :: AutoList Int 
    [2] :: AutoList Int 
    [3] :: AutoList Int 


main = print (toList foo) 

それがdo記法のためのモナドにする必要がありますが、型シグネチャなしでそれがでr ~()であることを把握することはできませんAutoListM Int r。明示的なタイプシグネチャでは、すべてを把握することができますが、これが本当に必要な解決策であるとは思えません。Writertellを使用するよりも多くの作業があります。また、あなたが本当にすべきではないものです。

+0

意味があります。私はこれまでWriterを使ってきましたが、私はこれを再び使用します。ありがとう! –

関連する問題