Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.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 单子;货柜;sigfpe和x27的练习;s博客_Haskell_Monads - Fatal编程技术网

Haskell 单子;货柜;sigfpe和x27的练习;s博客

Haskell 单子;货柜;sigfpe和x27的练习;s博客,haskell,monads,Haskell,Monads,我正在努力完成“向你学习哈斯凯尔”,现在是关于单子的章节。在其他Haskell相关的帖子中,我看到很多人推荐sigfpe关于monads的博客帖子;强烈建议Haskell的学生进行各种练习,让读者自己“发明”/“发现”单子的概念 我在容器练习的最后一步遇到了问题。我认为链接到他的网站是违反论坛规则的,所以我会尽我所能在这里描述它。(如果我在这方面错了,请恕我直言。)首先,我对这项活动的描述可能并不完全一致,因此一个简单的谷歌搜索可能是最好的:) 概述: 每一组练习都会引导读者完成构建不同类型单

我正在努力完成“向你学习哈斯凯尔”,现在是关于单子的章节。在其他Haskell相关的帖子中,我看到很多人推荐sigfpe关于monads的博客帖子;强烈建议Haskell的学生进行各种练习,让读者自己“发明”/“发现”单子的概念

我在容器练习的最后一步遇到了问题。我认为链接到他的网站是违反论坛规则的,所以我会尽我所能在这里描述它。(如果我在这方面错了,请恕我直言。)首先,我对这项活动的描述可能并不完全一致,因此一个简单的谷歌搜索可能是最好的:)

概述:

  • 每一组练习都会引导读者完成构建不同类型单子的步骤。这些步骤的概述如下:

      我们考虑了两个函数-<代码> f′<代码>和<代码> g′/代码>,它们具有相同的类型声明
    • 我们构造了一个函数(
      bind
      ),它允许我们组合
      f
      g
      ,这样输出就有意义了(一旦您看到下面的具体练习,可能会更有意义)。直接合成不起作用,因为
      f
      g
      的返回类型与其参数类型不匹配
    • 接下来,我们定义一个标识函数(
      单元
      ),以确保以下内容是正确的:
      (bind unit.f')==(bind f.unit)
    • 基于上一步,我们定义了一个
      lift
      函数,使得
      lift f=unit。f
    • 在最后一步中,我们被要求证明以下是正确的:
      bind(提升f)(提升g)=提升。绑定f g
以下是我正在进行的一系列练习:

    我们要求考虑两个函数:代码>SqRT 和<代码> CBRT ,它计算复数的平方根和立方根(即A+BI形式的数目,其中A和B是实数,而I是负的平方根)。基础数学并不重要。重要的是,可能的第n个根的数目是n。换句话说,复数(即a+bi形式)有两个复数的平方根,三个复数的立方根,等等
  • 考虑到复数根的性质,
    sqrt'
    cbrt'
    都接受类型为
    complex
    的参数,并返回类型为
    [complex]
    。我们被要求构造一个
    bind
    函数,它允许我们计算复数的第六个根,同时利用我们已经有了sqrt'和cbrt'这一事实。(直接合成obv不起作用)

    bind::(复数->[Complex)->[Complex]->[Complex]
    绑定f=(concat.map f)

  • 接下来,我们构造
    单元
    升降机

    unit::Complex->[Complex]
    单位x=[x]

    lift::(复杂->[Complex])->复杂->[Complex]
    提升f=单位f

  • 在最后一步中(这就是我遇到的问题),我们被要求展示以下内容:

    bind(提升f)(提升g)=提升。绑定f g

首先,这个等式的左边不是有一个类型不匹配吗?
lift
不能接受
[Complex]
类型的参数吗?退一步,我不知道我们为什么还要定义
unit
lift
。(我天真的自己认为,
bind
的定义解决了眼前的问题,因此接下来的问题就来了。)如果有人能帮助我理解为什么我们定义这两个函数,然后试图证明最后的等式,我将不胜感激


作为参考,我在下面附上我的代码。请注意,
bind
unit
lift
函数具有通用类型声明

bind :: (a1 -> [a]) -> [a1] -> [a]
bind f' = (concat . map f')

unit :: t -> [t]
unit x = [x]

lift :: (a -> b) -> a -> [b]
lift f = unit . f

--Definitions of cbRootC and sqRootC
data Complex = Complex Float Float deriving (Show)

cbrt' = rootC 3
sqrt' = rootC 2

rootC :: Float -> Complex -> [Complex]
rootC n (Complex a b) = zipWith Complex r i
            where r = map (* (mod ** (1/n) )) $ map cos $ map arg [0..n-1]
                  i = map (* (mod ** (1/n) )) $ map sin $ map arg [0..n-1]
                  arg  = ( * (2*pi / n) )
                  mod = sqrt (a*a + b*b)

您的第一个误解是在
lift
类型中。在对问题的描述中,您将其列为以下第一项,但在代码中,您有第二项

lift :: (Complex -> [Complex]) -> Complex -> [Complex]
lift :: (a       -> b        ) -> a       -> [b]
请注意,第二个定义如何在第一个参数的返回类型周围不包含
[]
。第二个定义是正确的。
lift
将获取一个普通函数
Complex->Complex
,并从中生成一个“多值”计算
Complex->[Complex]
,对于多个值,它只返回从普通函数返回的单个值

你的第二个误解与如何使用
*
有关。
*
用于组合“多值”计算;
f*g=bind f.g
用于普通函数组合

你没有被要求展示这一点

bind (lift f) (lift g) == lift . bind f g
没有进行类型检查是正确的。让我们试着做练习。
bind
应用于两个参数返回
[a]
lift
应用于单个参数返回
a1->[b]

bind (lift f) (lift g) == lift . bind f g
[a]                    ~  a1 -> [b]
无法选择
a
a1
b
,这将使列表
[]
和函数
->
具有相同的类型

而是要求您显示以下内容。请注意不同的符号
*
。我们将用
绑定
替换
*

      lift f  *  lift g  == lift (f . g)
bind (lift f) . (lift g) == lift (f . g)
我把剩下的练习留给你


unit
lift
之所以有用,是因为它们允许您重用您已有的普通类型的东西。
lift
将普通函数转换为“多值”计算,
unit
将普通值转换为“多值”结果计算。

感谢您的详细审查和回复。我确实没有看到