列出追加元素的monad实例

时间:2016-04-27 15:58:10

标签: haskell

是否可以使List的Monad实例像这样工作?

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

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

为了使这项工作,我需要一个约束,每个数组都有相同的类型:[Int]

1 个答案:

答案 0 :(得分:5)

你可以使用mtl Writer monad获得你想要的效果而且没什么可疯狂的:

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)

它必须是用于记号的monad,但如果没有类型签名,它就无法在r ~ ()中找出AutoListM Int r。使用明确的类型签名,它能够解决所有问题,但我怀疑这是您真正想要的解决方案,而且只需使用Writertell就可以做更多工作。此外,它只是你不应该做的事情。