热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

创建一个可以是多种类型的函数时遇到麻烦

如何解决《创建一个可以是多种类型的函数时遇到麻烦》经验,为你挑选了1个好方法。

我试图在Traceable类中创建一个单数函数,该函数让我同时使用二进制树和变量树,并输出所有可能的叶子路径列表的列表。我似乎无法编译,并且花了数小时试图弄清楚我的大脑。如果有人可以帮我,那将是惊人的。

这是我的代码

data Tree a = Null | Node a [Tree a] deriving Show
data BinTree a = Nil | Vertex a (BinTree a) (BinTree a) deriving Show

class Traceable a where
trace :: (BinTree a, Tree z) => z a -> [a]

instance Traceable (BinTree a) where{
trace Nil = []
trace (Vertex x l r) = trace l ++ [x] ++ trace 

instance Traceable (Tree a) where{
trace Null = []
trace (Node a x) = [a] ++ (trace (head x))}

我收到此错误

* Expected a constraint, but `BinTree a' has kind `*'
* In the type signature:
    trace :: (BinTree a, Tree z) => z a -> [a]
  In the class declaration for `Traceable'

* Expected a constraint, but `Tree z' has kind `*'
* In the type signature:
    trace :: (BinTree a, Tree z) => z a -> [a]
  In the class declaration for `Traceable'

* Expecting one fewer argument to `z'
  Expected kind `* -> *', but `z' has kind `*'
* In the type signature:
    trace :: (BinTree a, Tree z) => z a -> [a]
  In the class declaration for `Traceable'

编辑:这对我来说是一个学校项目,我不能使用任何Haskell扩展

按照您的建议做的事情还很多,但我仍然有一些错误。

* Expecting one fewer argument to `BinTree a'
  Expected kind `* -> *', but `BinTree a' has kind `*'
* In the first argument of `Traceable', namely `BinTree a'
  In the instance declaration for `Traceable (BinTree a)'

* Expecting one fewer argument to `Tree a'
  Expected kind `* -> *', but `Tree a' has kind `*'
* In the first argument of `Traceable', namely `Tree a'
  In the instance declaration for `Traceable (Tree a)'

编辑#2感谢您的帮助,从BinTree实例中删除a似乎造成了另一个问题

* Couldn't match expected type `[a]'
              with actual type `t0 a0 -> [a0]'
* In the second argument of `(++)', namely `trace'
  In the second argument of `(++)', namely `[x] ++ trace'
  In the expression: trace l ++ [x] ++ trace
* Relevant bindings include
    r :: BinTree a (bound at tree.hs:11:20)
    l :: BinTree a (bound at tree.hs:11:18)
    x :: a (bound at tree.hs:11:16)
    trace :: BinTree a -> [a] (bound at tree.hs:10:2)

leftaroundab.. 7

错误的原因仅仅是该trace方法的签名。谈论BinTreeTree在那里没有意义-这些是该类的实例,并且会在您声明时及时(而instance不是在声明内)提及。你想要的是

class Traceable t where
  trace :: t a -> [a]

然后应该写实例

instance Traceable BinTree where
  trace Nil = []
  ...
instance Traceable Tree where
  ...

There's another problem in the Tree instance: trace (head x) just creates the trace for the first subtree in the node. For one thing, that's not even guaranteed to exist (there could be zero branches), for another, there will typically be multiple other branches that are ignored this way. What you want to do is recurse into all the branches, i.e. for all the elements in the x list. “Doing something for all things in a list” generally suggests that you could use map. So, map trace x. However, that has type [[a]] (because each trace generates [a], and you end up with a list of those lists.

What you want to do is concatenate all of those lists together. That can be done with, wait for it: concat.

  trace (Node a x) = [a] ++ concat (map trace x)

...or more elegantly

  trace (Node a x) = a : concat (trace <$> x)

实际上,映射和串联的组合非常普遍,以至于存在一个标准功能:concatMap。而且,它是臭名昭著的Monad类型类的特征方法,其中列表是一个实例。知道了,你可以写

  trace (Node a x) = a : (trace =<

很好

但实际上,您不需要执行任何操作,因为将多态容器的所有字段聚集在一起的想法也是非常普遍的,并且可以自动处理。这是推荐的解决方案:

{-# LANGUAGE DeriveFunctor, DeriveFoldable #-}

import Data.Foldable

data Tree a = Null | Node a [Tree a]
 deriving (Show, Functor, Foldable)
data BinTree a = Nil | Vertex (BinTree a) a (BinTree a)
 deriving (Show, Functor, Foldable)

然后简单地trace = toList



1> leftaroundab..:

错误的原因仅仅是该trace方法的签名。谈论BinTreeTree在那里没有意义-这些是该类的实例,并且会在您声明时及时(而instance不是在声明内)提及。你想要的是

class Traceable t where
  trace :: t a -> [a]

然后应该写实例

instance Traceable BinTree where
  trace Nil = []
  ...
instance Traceable Tree where
  ...

There's another problem in the Tree instance: trace (head x) just creates the trace for the first subtree in the node. For one thing, that's not even guaranteed to exist (there could be zero branches), for another, there will typically be multiple other branches that are ignored this way. What you want to do is recurse into all the branches, i.e. for all the elements in the x list. “Doing something for all things in a list” generally suggests that you could use map. So, map trace x. However, that has type [[a]] (because each trace generates [a], and you end up with a list of those lists.

What you want to do is concatenate all of those lists together. That can be done with, wait for it: concat.

  trace (Node a x) = [a] ++ concat (map trace x)

...or more elegantly

  trace (Node a x) = a : concat (trace <$> x)

实际上,映射和串联的组合非常普遍,以至于存在一个标准功能:concatMap。而且,它是臭名昭著的Monad类型类的特征方法,其中列表是一个实例。知道了,你可以写

  trace (Node a x) = a : (trace =<

很好

但实际上,您不需要执行任何操作,因为将多态容器的所有字段聚集在一起的想法也是非常普遍的,并且可以自动处理。这是推荐的解决方案:

{-# LANGUAGE DeriveFunctor, DeriveFoldable #-}

import Data.Foldable

data Tree a = Null | Node a [Tree a]
 deriving (Show, Functor, Foldable)
data BinTree a = Nil | Vertex (BinTree a) a (BinTree a)
 deriving (Show, Functor, Foldable)

然后简单地trace = toList


推荐阅读
  • 本文介绍如何在 Unity 的 XML 配置文件中,将参数传递给自定义生命周期管理器的构造函数。我们将详细探讨 CustomLifetimeManager 类的实现及其配置方法。 ... [详细]
  • Hadoop入门与核心组件详解
    本文详细介绍了Hadoop的基础知识及其核心组件,包括HDFS、MapReduce和YARN。通过本文,读者可以全面了解Hadoop的生态系统及应用场景。 ... [详细]
  • 本文详细探讨了Java中StringBuffer类在不同情况下的扩容规则,包括空参构造、带初始字符串和指定初始容量的构造方法。通过实例代码和理论分析,帮助读者更好地理解StringBuffer的内部工作原理。 ... [详细]
  • 本文探讨了领域驱动设计(DDD)的核心概念、应用场景及其实现方式,详细介绍了其在企业级软件开发中的优势和挑战。通过对比事务脚本与领域模型,展示了DDD如何提升系统的可维护性和扩展性。 ... [详细]
  • 深入了解 Windows 窗体中的 SplitContainer 控件
    SplitContainer 控件是 Windows 窗体中的一种复合控件,由两个可调整大小的面板和一个可移动的拆分条组成。本文将详细介绍其功能、属性以及如何通过编程方式创建复杂的用户界面。 ... [详细]
  • 实体映射最强工具类:MapStruct真香 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
  • 本文探讨了在Linux系统上使用Docker时,通过volume将主机上的HTML5文件挂载到容器内部指定目录时遇到的403错误,并提供了解决方案和详细的操作步骤。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • 作为一名专业的Web前端工程师,掌握HTML和CSS的命名规范是至关重要的。良好的命名习惯不仅有助于提高代码的可读性和维护性,还能促进团队协作。本文将详细介绍Web前端开发中常用的HTML和CSS命名规范,并提供实用的建议。 ... [详细]
  • 本文探讨了在 ASP.NET MVC 5 中实现松耦合组件的方法。通过分离关注点,应用程序的各个组件可以更加独立且易于维护和测试。文中详细介绍了依赖项注入(DI)及其在实现松耦合中的作用。 ... [详细]
  • Startup 类配置服务和应用的请求管道。Startup类ASP.NETCore应用使用 Startup 类,按照约定命名为 Startup。 Startup 类:可选择性地包括 ... [详细]
  • 网易严选Java开发面试:MySQL索引深度解析
    本文详细记录了网易严选Java开发岗位的面试经验,特别针对MySQL索引相关的技术问题进行了深入探讨。通过本文,读者可以了解面试官常问的索引问题及其背后的原理。 ... [详细]
  • 自己用过的一些比较有用的css3新属性【HTML】
    web前端|html教程自己用过的一些比较用的css3新属性web前端-html教程css3刚推出不久,虽然大多数的css3属性在很多流行的浏览器中不支持,但我个人觉得还是要尽量开 ... [详细]
  • 本文将深入探讨如何在不依赖第三方库的情况下,使用 React 处理表单输入和验证。我们将介绍一种高效且灵活的方法,涵盖表单提交、输入验证及错误处理等关键功能。 ... [详细]
author-avatar
black李曼_827
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有