Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 如何将返回[]的函数转换为可遍历函数?_List_Haskell_Traversable - Fatal编程技术网

List 如何将返回[]的函数转换为可遍历函数?

List 如何将返回[]的函数转换为可遍历函数?,list,haskell,traversable,List,Haskell,Traversable,我有以下模块实现目录漫游: 模块漫游 (步行 )在哪里 进口管制 导入控制.Monad.IO.Class 导入数据。列表 导入系统目录 导入System.FilePath walk::(MonadIO m)=>FilePath->m[(FilePath,[FilePath])] 走根=做 条目*)(t::*->*)。 (MonadIO m,可遍历t)=> FilePath->m(t(FilePath,[FilePath])) 预期类型:m(t(FilePath,[FilePath])) 实际类型

我有以下模块实现目录漫游:

模块漫游
(步行
)在哪里
进口管制
导入控制.Monad.IO.Class
导入数据。列表
导入系统目录
导入System.FilePath
walk::(MonadIO m)=>FilePath->m[(FilePath,[FilePath])]
走根=做
条目*)(t::*->*)。
(MonadIO m,可遍历t)=>
FilePath->m(t(FilePath,[FilePath]))
预期类型:m(t(FilePath,[FilePath]))
实际类型:m[(FilePath,[FilePath])]
•在“do”块的stmt中:
((根,映射fst文件):)。海螺
mapM(walk.(root).fst)dirs
在表达式中:
输入
我认为它在
上失败了


的确如此。如果使用
(:)
构建结构,该结构将是一个列表,并且不能更改
walk
的类型以声明它返回任意可遍历的结构。实际上也没有一个好的以
可遍历
为中心的解决方法:
可遍历
意味着,通过它的
可折叠
超类,您有一个
toList
,但没有一个
fromList
列表的多态生成,并且通常为多态容器设计类,事实证明,这比最初看起来要困难得多。GHC目前生产完全多态容器的解决方案是
IsList
类,而不是只在预先存在的容器上操作,例如使用
Traversable

GHC.Exts
中定义为:

class IsList l where
  type Item l
  fromList  :: [Item l] -> l
  ...
已经有列表、非空列表、映射和大多数其他类型的实例,它们来自于您认为的标准Haskell库

请注意,类型参数
l
,属于
*
类型,而不是您从
*->*
容器中所期望的类型。您可以提供完全应用的类型,并且如果需要,可以使用类型相等来约束
项l
类型。例如:

{-# LANGUAGE TypeFamilies #-}
module Walk
  ( walk
  ) where

import           Control.Monad
import           Control.Monad.IO.Class
import           Data.List
import           System.Directory
import           System.FilePath
import           GHC.Exts

walk :: (IsList l, Item l ~ (FilePath,[FilePath]), MonadIO m) => FilePath -> m l
walk root =
  do entries <- liftIO $ listDirectory root
     (files, dirs) <- partition snd <$> liftM2 (<$>) zip (mapM (liftIO . doesFileExist . (root </>))) entries
     fromList . ((root, map fst files) :) . concat <$> mapM (walk . (root </>) . fst) dirs
{-#语言类型族}
模块步行
(步行
)在哪里
进口管制
导入控制.Monad.IO.Class
导入数据。列表
导入系统目录
导入System.FilePath
导入GHC.Exts
walk::(IsList l,Item l~(FilePath,[FilePath]),MonadIO m)=>FilePath->ml
步行根=

您知道通用版本的用途是什么吗?我倾向于认为让
walk
返回一个特定的结构(可以是列表、地图或其他东西),然后在单独的步骤中将其转换为其他内容就足够了,但这可能有助于准确地了解您的预期用例。这可以通过查看可遍历方法的类型签名来确定。它们都将可遍历的
t
置于负位置,因此不能用于生成任意的
t
结果。
{-# LANGUAGE TypeFamilies #-}
module Walk
  ( walk
  ) where

import           Control.Monad
import           Control.Monad.IO.Class
import           Data.List
import           System.Directory
import           System.FilePath
import           GHC.Exts

walk :: (IsList l, Item l ~ (FilePath,[FilePath]), MonadIO m) => FilePath -> m l
walk root =
  do entries <- liftIO $ listDirectory root
     (files, dirs) <- partition snd <$> liftM2 (<$>) zip (mapM (liftIO . doesFileExist . (root </>))) entries
     fromList . ((root, map fst files) :) . concat <$> mapM (walk . (root </>) . fst) dirs