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 也许你没有';对一个函数应用的参数是否足够?_Haskell - Fatal编程技术网

Haskell 也许你没有';对一个函数应用的参数是否足够?

Haskell 也许你没有';对一个函数应用的参数是否足够?,haskell,Haskell,我在大学的一门课程中学习Haskell,有一个考试练习,我们需要定义一个函数,它包含一系列函数[(Int->Int)]和另一个Int类型的参数,并返回一个Int。所以类型应该是 compose :: [(Int ->Int)] -> Int -> Int. 函数应该从左到右返回列表中函数的组合,并将其应用于第二个参数。 我尝试了以下方法: compose :: [(Int -> Int)] -> Int -> Int compose [] x = x com

我在大学的一门课程中学习Haskell,有一个考试练习,我们需要定义一个函数,它包含一系列函数
[(Int->Int)]
和另一个
Int
类型的参数,并返回一个
Int
。所以类型应该是

compose :: [(Int ->Int)] -> Int -> Int.
函数应该从左到右返回列表中函数的组合,并将其应用于第二个参数。 我尝试了以下方法:

compose :: [(Int -> Int)] -> Int -> Int
compose [] x = x
compose (f:fs) x  
    |fs == [] = f x
    |f  : (compose fs x)
但是编译器抛出一个错误:

003Exam.hs:24:22:
    Couldn't match expected type ‘Int’ with actual type ‘[Int -> Int]’
    In the expression: f : (compose fs x)
    In an equation for ‘compose’:
        compose (f : fs) x
          | fs == [] = f x
          | otherwise = f : (compose fs x)

003Exam.hs:24:28:
    Couldn't match expected type ‘[Int -> Int]’ with actual type ‘Int’
    In the second argument of ‘(:)’, namely ‘(compose fs x)’
    In the expression: f : (compose fs x)
如果我离开最后一行,比如:

compose :: [(Int -> Int)] -> Int -> Int
compose [] x = x
compose (f:fs) x  
    |fs == [] = f x
然后我也得到了一个错误-这是一个我真的不明白的错误:

003Exam.hs:23:13:
    No instance for (Eq (Int -> Int))
      (maybe you haven't applied enough arguments to a function?)
      arising from a use of ‘==’
    In the expression: fs == []
    In a stmt of a pattern guard for
               an equation for ‘compose’:
      fs == []
    In an equation for ‘compose’: compose (f : fs) x | fs == [] = f x
我很高兴能得到任何帮助,澄清我做错了什么

|f  : (compose fs x)
    ^
我想你的问题是这个冒号不应该在这里。
Haskell中的
是列表构造函数,这就是为什么编译器告诉您正在尝试返回
[Int->Int]
。如果它不在那里,f将被简单地应用,并且您将返回一个
Int

,您必须对结果重复应用函数,并且空函数列表应被视为id

Prelude> let comp :: [(Int->Int)] -> Int -> Int
Prelude|     comp [] x = x
Prelude|     comp (f:fs) x = comp fs (f x)
Prelude|
Prelude> comp [(^2),(+1)] 3
10
我看错了问题,上面是从左到右应用函数。如果你是从左到右作曲(首先应用最右边的函数),应该是这样的(现在是无点)

首先,
(:)
仅用于在列表前面添加元素(或与这些元素匹配的模式),因此必须替换

f : compose fs x

接下来,您必须在保护中使用类型为
Bool
的表达式或模式匹配:

| fs == []  = -- this line is still wrong, see below
| otherwise = f (compose f xs)
但是,没有函数的
Eq
实例。两个函数的等价性是不可判定的(通常),因此使用
null::[a]->Bool
而不是
(==)::Eq a=>[a]->[a]->Bool

compose :: [(Int -> Int)] -> Int -> Int
compose [] x = x
compose (f:fs) x  
  | null fs   = f x
  | otherwise = f (compose fs x)
由于
compose[]x
x
相同,您甚至可以删除该复选框:

compose :: [(Int -> Int)] -> Int -> Int
compose []     x = x
compose (f:fs) x = f (compose fs x)
练习
  • 扩展
    compose[(+1),(+2)]1
    (用其定义替换它),而不删除中间术语。你注意到一种模式了吗
  • 这个模式会让你想起库函数吗
  • 尝试使用该库函数来编写
    compose

几小时后,让我提供一些关于将此作为折页书写的提示。因为有两个方向可以组合函数,而我不知道如何正确地组合函数,所以我只展示这两个方向

首先,一些样板:

import Data.Monoid (Dual (..))
import Control.Category (Category (..))
import Data.Foldable (Foldable (foldMap))
import Prelude hiding (id, (.))
接下来,一个类型解释了幺半群是一个只有一个对象的类别:

newtype Cat c a = Cat { getCat :: c a a }

instance Category c => Monoid (Cat c a) where
  mempty = Cat id
  mappend (Cat f) (Cat g) = Cat (f . g)
最后,您寻找的函数,从
->
概括为任意
类别

compose1 :: (Foldable f, Category c) => f (c a a) -> c a a
compose1 = getCat . foldMap Cat

compose2 :: (Foldable f, Category c) => f (c a a) -> c a a
compose2 = getCat . getDual . foldMap (Dual . Cat)
读者练习:编写等效函数,将
类别
替换为
半群体
,将
可折叠
替换为
可折叠

读者的另一个练习是:使用
Data.concure.concure
和/或
#.
#
Data.Profunctor.Unsafe
编写
幺半群(Cat c a)
实例,以避免错误的闭包分配


另外,
Cat
类型只能解释一半的情况。以下是剩下的:

newtype Mon m a b = Mon m

instance Monoid m => Category (Mon m) where
  id = Mon mempty
  Mon m . Mon n = Mon (m `mappend` n)
可以说,使用它会更精确

data Mon m a b where
  Mon :: m -> Mon m a a

但是如果没有真正增加太多的价值,这将是效率较低的。

关于
fs=[]
和“没有(Eq(Int->Int))的实例”还有另一个问题,这改变了原始函数的语义,因为
comp[negate,(+2)]3
在问题中是
-5
,但在您的变体中是
-1
。哇,非常感谢大家。我刚吃了一些意大利面条,当我回到这里时,有很多定性的答案。现在我相信我明白了问题所在。非常感谢。(我想你是说折叠?):谢谢all@DavidJambalaya不客气。请注意,这样其他人就知道您的问题已经得到了回答。您可以随时更改已接受的答案。aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa。是的,这是一个褶皱。不过,我不会告诉你是哪一个:D.你说的“哪一个折叠”是什么意思
foldMap
无论如何都会成功@dfeuer
foldMap Endo
是一个巧妙的技巧;/对于新手来说,这是一种黑暗魔法用<代码>折叠*>代码>你几乎是按PART/如果你用<代码> L>代码>或<代码> R>代码>来代替<代码> */COD>。至少直到默认的书籍使用后FTP材质。你的答案是完全脱钩的。请不要将此视为批评/但你的回答离题了。我不确定它们走了多远,但考虑到语法错误,我认为它们没有处理
可折叠的
幺半群
。另外,如果你没有回答最初的问题,你正在使用轨道加农炮射杀一棵树,但有点错过了。毕竟,
compose1=foldr(.)id
compose2=foldr(flip(.)id
(带有
Control.Category
)。好吧,不是100%偏离主题,你提供了一个有效的
compose
,但你明白了我的意思(而且“评论”的押韵真的很好;但你不知道我最近为什么要押韵)。@Zeta,这不太正确,例如,由于无限snoc列表可能使用我的代码在某些类别中给出结果,但从不使用
foldr
。当然,可能应该添加“在这个问题的上下文中”。对于“如何将
可折叠的
中的自同态折叠为单个自同态”,您的答案非常准确。(你不需要偶尔睡觉吗?@Zeta,我试过了,但我不太擅长在合理的时间睡觉。
newtype Mon m a b = Mon m

instance Monoid m => Category (Mon m) where
  id = Mon mempty
  Mon m . Mon n = Mon (m `mappend` n)
data Mon m a b where
  Mon :: m -> Mon m a a