如何在不必在Haskell中使用算术运算符的情况下添加?

时间:2017-09-08 12:15:13

标签: haskell

我是Haskell的新手,我正试图弄清楚如何添加而不必使用'+'符号。我正在使用Winhugs作为编译器。

让我们说, cookies = 10,巧克力= 5,蛋糕= 20

如果我进入,

  

cookies 1 chocolate 1

输出应该是,

  

15

这就是我所拥有的

cookies :: Int -> Int
cookies 1 = 10
cookies n = 10 + cookies (n-1)

chocolate :: Int -> Int
chocolate 1 = 5
chocolate n = 5 + chocolate (n-1)

我必须进入,

  

cookies 1 + chocolate 1

为了得到15.还有另一种方法吗?

我也试过使用递归类型,但我仍然觉得它很混乱。我也尝试了这个,但我只能添加两个项目,我总是要输入cookie:

cookies ::  Int -> (Int -> Int) -> Int -> Int 
cookies x item y = (x * 20) + item y

cake :: Int -> Int
cake 1 = 20
cake n = 20 + cake (n-1)

chocolate :: Int -> Int
chocolate 1 = 5
chocolate n = 5 + chocolate (n-1)

另外,我不能只输入cookie,因为它应该总是有另一个项目。

  

cookies 1

     

错误 - 无法找到“显示”功能:

     

***表达:cookies 1

     

***类型:(Int - > Int) - > Int - > INT

我很抱歉这个非常棒的问题。谢谢所有可以提供帮助的人!

**更新** 我知道我可以使用不同的编译器,但它是在学校教授的内容,它也是我们需要用于我们项目的编译器:(

3 个答案:

答案 0 :(得分:6)

我不明白为什么你想要这一切。您尝试实施的内容称为variadic function。 Haskell并不真正支持这些,我真的不相信将它们用于您的应用程序是有意义的。 cookies 1 + chocolate 2出了什么问题?

也就是说,Haskell2010 / GHC-Haskell类型系统足够灵活,可以将各种可变功能混合在一起:

{-# LANGUAGE TypeFamilies, FlexibleInstances #-}

class Crumbles c where
  crumble :: Int -> c
instance Crumbles Int where
  crumble = id
instance (f ~ (Int -> Int), i ~ Int, Crumbles c) => Crumbles (f -> i -> c) where
  crumble acc f i = crumble $ f i + acc

现在你可以做到

cookies :: Crumbles c => Int -> c
cookies n = crumble $ n*10

chocolate :: Crumbles c => Int -> c
chocolate n = crumble $ n*5

goodies :: [Int]
goodies = [ cookies 1  -- 10
          , cookies 1 chocolate 1   -- 15
          , cookies 1 chocolate 1 cookies 100000  -- 1000015
          ]

main :: IO ()
main = print goodies

......给予[10,15,1000015]

我不知道Hugs是否支持等式约束TypeFamiliesf ~ (Int -> Int)所需的i ~ Int扩展名。

我怀疑任务的用途是完全不同的,即如何实现 cookies :: Int -> Int而不使用加法或乘法,即不写*1010 + cookies (n-1)。他们可能想要的答案应该只使用succpred函数(分别相当于+1-1)。

答案 1 :(得分:2)

不要尝试编写名为cookieschocolate的函数,这些函数在输入hugs解释器时会表现得那样。

相反,尝试编写一个IO动作,接受输入,解析它,并进行适当的计算。您可能喜欢interact函数,该函数在String上执行函数并在用户键入的内容上运行它:

interact :: (String -> String) -> IO ()

例如,使用runhaskell(与拥抱非常相似),代码如下:

main = interact $ \s ->
    "What is your name?\n" ++
    filter (/='\n') s ++ ", nice to meet you!\n"

产生以下互动:

% runhaskell test.hs
What is your name?
Daniel
Daniel, nice to meet you!

请注意,我在输入Daniel并按回车键后按下了EOF按钮;在Linux上这是ctrl-d但我相信在Windows上它是ctrl-z。另请注意,代码中没有Daniel的定义 - 我输入的Daniel而不是一个Haskell术语,而是通过运行Haskell术语main

答案 2 :(得分:1)

像Daniel Wagner一样,我怀疑这个问题是错误的。我发现很难相信作业要求可以这种方式组合的函数cookieschocolate。相反,它可能要求函数calculate :: String -> Int接受字符串 "cookies 1 chocolate 2",解析它,并返回结果。

为此,解决方案非常简单 - 所以我不会放弃它。将问题分解为以下小步骤:

  • "cookies 1 chocolate 2"

  • ["cookies", "1", "chocolate", "2"]

  • [("cookies", 1), ("chocolate", 2)]

  • [10, 10]

  • 20

为每个步骤编写一个函数,并为要求输入的main编写函数并调用这些函数来计算最终结果。如果您考虑如何使用MaybeEither来处理输入中的错误,例如未知项目,非数字数量,缺失数量和& c。

,则可获得奖励积分