我试图使用Data.Traversable在haskell中遍历数据结构的所有成员,该文件记录在以下URL中:

http://hackage.haskell.org/package/base-4.6.0.1/docs/Data-Traversable.html
http://www.haskell.org/haskellwiki/Foldable_and_Traversable

到目前为止,我想出了以下代码,据我所知,这些代码缺少Tr.Traversable实例化的正确实现。

import qualified Data.Traversable as Tr
import qualified Data.Foldable as Fl
import Control.Monad
import Control.Applicative

data Test = Test { desc  :: String
                 , value :: Int
}

data Data t = Data { foo :: t
                   , bar :: t
}

exampleData = Data { foo = Test "Foo" 1
                   , bar = Test "Bar" 2
}

instance Show Test where
  show f = (desc f) ++ ": " ++ (show $ value f)

instance (Show a) => Show (Data a) where
  show f = show (foo f)

instance Functor Data where
  fmap = Tr.fmapDefault

instance Fl.Foldable Data where
  foldMap = Tr.foldMapDefault

instance Tr.Traversable Data where
    traverse f = Data f  -- Try to show a Test entry inside the Data structure

--
--  traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
--

main = do
  putStrLn $ show exampleData
  Tr.traverse (putStrLn show) exampleData

我正在尝试打印exampleData中的所有项目,逐个成员并使用show。我是否走在正确的道路上,应该如何实现可遍历的实例化?

最佳答案

我只是使用语言扩展为我派生它:

{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE DeriveFoldable #-}
import qualified Data.Traversable as Tr
import qualified Data.Foldable as Fl
import Control.Monad
import Control.Applicative

data Test = Test { desc  :: String
                 , value :: Int }

data Data t = Data { foo :: t
                   , bar :: t } deriving (Functor, Tr.Traversable, Fl.Foldable)

exampleData = Data { foo = Test "Foo" 1
                   , bar = Test "Bar" 2
}

instance Show Test where
  show f = (desc f) ++ ": " ++ (show $ value f)

instance (Show a) => Show (Data a) where
  show f = show (foo f)

main = do
  putStrLn $ show exampleData
  Tr.traverse (putStrLn . show) exampleData
> runhaskell test_traversable.hs
Foo: 1
Foo: 1
Bar: 2
()

如果您想知道编译器是如何自动实现的,可以使用-ddump-deriv标志对其进行编译(稍作清理):
instance Functor Data where
  fmap f (Data foo' bar') = Data (f foo') (f bar')

instance Tr.Traversable Data where
  tr.traverse f (Data foo' bar') = Data <$> (f foo') <*> (f bar')

instance Fl.Foldable Data where
  Fl.foldr f z (Data foo' bar') = f foo' (f bar' z)

10-06 07:17