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
Haskell中用于可前置列表的Data.List和Data.Sequence的最小接口_Haskell - Fatal编程技术网

Haskell中用于可前置列表的Data.List和Data.Sequence的最小接口

Haskell中用于可前置列表的Data.List和Data.Sequence的最小接口,haskell,Haskell,我发现我正在编写重复函数来处理Data.List和Data.Sequence,为了对它们进行概括,我写了: import qualified Data.Sequence as Seq class PrependableList pl where empty :: pl a first :: pl a -> a prepend :: a -> pl a -> pl a len :: pl a -> Int instance PrependableLis

我发现我正在编写重复函数来处理Data.List和Data.Sequence,为了对它们进行概括,我写了:

import qualified Data.Sequence as Seq

class PrependableList pl where
  empty :: pl a
  first ::  pl a -> a
  prepend :: a -> pl a -> pl a
  len :: pl a -> Int

instance PrependableList [a] where
  empty = []
  first = head
  prepend = (:)
  len = length

instance PrependableList (Seq.Seq a) where
  empty = Seq.empty
  first seq = Seq.index seq 0
  prepend = (Seq.<|)
  len = Seq.length
从我在其他条目(例如)中看到的情况来看,可能不可能完全概括多个类似列表的数据结构


但是,上述4个函数是否至少可以推广到Data.List和Data.Sequence?

多亏了大家,这是正确的代码,只提供了一个简单的用法示例:

    import qualified Data.Sequence as Seq

    class PrependableList pl where
        empty :: pl a
        first ::  pl a -> a
        prepend :: a -> pl a -> pl a
        len :: pl a -> Int

    instance PrependableList [] where
        empty = []
        first = head
        prepend = (:)
        len = length

    instance PrependableList Seq.Seq where
        empty = Seq.empty
        first seq = Seq.index seq 0
        prepend = (Seq.<|)
        len = Seq.length

    -- Example usage
    prependAll :: (PrependableList pl) => pl a -> [a] -> pl a
    prependAll plist xs = foldr prepend plist xs

    main = do
        print $ prependAll Seq.empty [1..5]
        print $ prependAll [] [1..5]

感谢大家,这是正确的代码,只提供了一个简单的用法示例:

    import qualified Data.Sequence as Seq

    class PrependableList pl where
        empty :: pl a
        first ::  pl a -> a
        prepend :: a -> pl a -> pl a
        len :: pl a -> Int

    instance PrependableList [] where
        empty = []
        first = head
        prepend = (:)
        len = length

    instance PrependableList Seq.Seq where
        empty = Seq.empty
        first seq = Seq.index seq 0
        prepend = (Seq.<|)
        len = Seq.length

    -- Example usage
    prependAll :: (PrependableList pl) => pl a -> [a] -> pl a
    prependAll plist xs = foldr prepend plist xs

    main = do
        print $ prependAll Seq.empty [1..5]
        print $ prependAll [] [1..5]
我知道你已经自己回答了这个问题,但我想指出的是,Haskell近年来一直在努力更广泛地封装这些想法,而你的类已经是其他两个现有类的组合:

进口控制。单子单子,mzero,mplus; 导入数据。可折叠,长度,toList; 导入数据 导入符合条件的数据。顺序为S -与您的PrependableList相同 类可前置的p,其中 空::p a 第一:p a->a 前置::a->PA->PA len::pa->Int -通用新型包装器 新类型WrapP px=WrapP{unwrapP::px}派生Show,Eq,Ord -任何可折叠的monadplus都是可预折叠的。 实例MonadPlus m,Foldable m=>Prependable WrapP m其中 空=WrapP mzero prepend=WrapP。打开包装。mplus。回来 第一个=头。托利斯特。展开 len=长度。展开 -具体案例 类型SeqP x=包装Seq x 类型ListP x=WrapP[]x 此外,由于WrapP是一种新类型,您通常可以用id替换WrapP和unwrapP,只要您还调整了类型签名;特别是,我们可以将您的四个函数直接编写为:

空::可折叠的m,MonadPlus m=>mx 空=零 第一个::可折叠的m,MonadPlus m=>mx->x 第一个=头。托利斯特 可折叠的m,MonadPlus m=>x->MX->MX prepend=mplus。回来 len::可折叠的m,MonadPlus m=>mx->Int len=长度 现在这些将在列表和Data.Sequence上运行。如果Prelude.length与Data.Foldable.length不同,则可能需要更新的ish版本的GHC,或者必须导入Prelude隐藏长度,然后从Data.Foldable显式导入

由于Data.Sequence已经为Seq定义了MonadPlus和Foldable,您可以使用8行代码,而不需要新的类或实例声明;此外,其中两个是长度的直接替换len,mzero为空,如果您只使用已经为您定义的版本,则可以再节省4行代码

作为一个小小的迂回,首先也是从控件中提取。Comonad,用一个非空的!列表的摘录是head,副本是take,而不是。无效的尾部使用Data.List.tails,但忽略最后一个元素[]。我不认为你可以纯粹基于一个Comonad基础设施来定义len;为此,你真的需要一个可折叠的类型。通过将非空列表写成newtype NEList=NEList x Maybe NEList x,我们可以将其替换为Cofree Maybe,从而使其成为明显的comonad形式。

我知道你已经自己回答了这个问题,但我想指出的是,Haskell近年来一直在努力更广泛地封装这些想法,而你的类已经是其他两个现有类的组合:

进口控制。单子单子,mzero,mplus; 导入数据。可折叠,长度,toList; 导入数据 导入符合条件的数据。顺序为S -与您的PrependableList相同 类可前置的p,其中 空::p a 第一:p a->a 前置::a->PA->PA len::pa->Int -通用新型包装器 新类型WrapP px=WrapP{unwrapP::px}派生Show,Eq,Ord -任何可折叠的monadplus都是可预折叠的。 实例MonadPlus m,Foldable m=>Prependable WrapP m其中 空=WrapP mzero prepend=WrapP。打开包装。mplus。回来 第一个=头。托利斯特。展开 len=长度。展开 -具体案例 类型SeqP x=包装Seq x 类型ListP x=WrapP[]x 此外,由于WrapP是一种新类型,您通常可以用id替换WrapP和unwrapP,只要您还调整了类型签名;特别是,我们可以将您的四个函数直接编写为:

空::可折叠的m,MonadPlus m=>mx 空=零 第一个::可折叠的m,MonadPlus m=>mx->x 第一个=头。托利斯特 可折叠的m,MonadPlus m=>x->MX->MX prepend=mplus。回来 len::可折叠的m,MonadPlus m=>mx->Int len=长度 现在这些将在列表和Data.Sequence上运行。如果Prelude.length与Data.Foldable.length不同,则可能需要更新的ish版本的GHC,或者必须导入Prelude隐藏长度,然后从Data.Foldable显式导入

作为Data.Sequence已经为Seq定义了MonadPlus和Foldable, 您可以使用8行代码,没有新的类或实例声明;此外,其中两个是长度的直接替换len,mzero为空,如果您只使用已经为您定义的版本,则可以再节省4行代码


作为一个小小的迂回,首先也是从控件中提取。Comonad,用一个非空的!列表的摘录是head,副本是take,而不是。无效的尾部使用Data.List.tails,但忽略最后一个元素[]。我不认为你可以纯粹基于一个Comonad基础设施来定义len;为此,你真的需要一个可折叠的类型。通过将非空列表写成newtype NEList=NEList x Maybe NEList x,我们可以将非空列表替换为Cofree Maybe,看看它是一个comonad。只需将[A]更改为[]。正如错误消息所指出的,PrependableList需要一元类型构造函数*->*,而不是空类型构造函数*。因此,您应该编写实例PrependableList[]和实例PrependableList Seq.Seq。此外,除非使用限定名Thanke@MathematicalArchid,否则代码片段不会编译,这确实克服了编译错误。接下来的问题是如何在函数的类型定义中使用PrependableList。当我添加PrependableList a时,编译器指出了另一种类型的不匹配:kind mis match PrependableList的第一个参数'should has kind*->',但是'has kind'不能使星号正确显示anks@Jubobs-修复了Seq。@AlbertCardona您想要类似PrependableList pl=>pl a的东西。只需将[a]改为[]。正如错误消息所指出的,PrependableList需要一元类型构造函数*->*,而不是空构造函数*。因此,您应该编写实例PrependableList[]和实例PrependableList Seq.Seq。此外,除非使用限定名Thanke@MathematicalArchid,否则代码片段不会编译,这确实克服了编译错误。接下来的问题是如何在函数的类型定义中使用PrependableList。当我添加PrependableList a时,编译器指出另一种类型不匹配:kind mis match PrependableList的第一个参数'should has kind*->',但是'has kind'不能使星号正确显示anks@Jubobs-修复了Seq。@AlbertCardona您想要类似PrependableList pl=>pl a的东西。
$ ./pl 
fromList [1,2,3,4,5]
[1,2,3,4,5]