是否可以使List的Monad实例像这样工作?
foo = do
[1]
[2]
[3]
main = print foo -- prints [1,2,3]
为了使这项工作,我需要一个约束,每个数组都有相同的类型:[Int]
。
答案 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
。使用明确的类型签名,它能够解决所有问题,但我怀疑这是您真正想要的解决方案,而且只需使用Writer
和tell
就可以做更多工作。此外,它只是你不应该做的事情。