繁体   English   中英

haskell 中的 Skyline,可能是因为“函数”应用于太少的参数

[英]Skyline in haskell, probably cause ´function´is applied to too few arguments

我正在为大学学习 Haskell,我正在尝试解决 Skyline 问题 -> https://briangordon.github.io/2014/08/the-skyline-problem.html

我对 haskell 语法有严重的问题,因为我来自 OO 语言,FP 对我来说很奇怪,所以,这是我当前的代码:

    type Edificio = (Int,Int,Int)
type Coordenada = (Int,Int)
type Skyline = [Coordenada]

resuelveSkyline :: [Edificio] -> Skyline
resuelveSkyline [] = []
resuelveSkyline [x] = edificioAskyline(x)
resuelveSkyline xs = combina (resuelveSkyline(fst(divide(xs))),resuelveSkyline(snd(divide(xs))))

edificioAskyline :: Edificio -> Skyline
edificioAskyline (x1,x2,h) = [(x1,h),(x2,0)]

divide :: [Edificio] -> ([Edificio], [Edificio])
divide edificios = splitAt (((length edificios) + 1) `div` 2) edificios

combina :: Skyline -> Skyline -> Skyline
combina (_,_) = []

我有两个问题,第一个是:

例如,我有一个 Coordenada 类型,如果我想将 Coordenada 作为参数传递给其他函数并在其中获取他的第一个元组值,我该怎么办?

第二个是,我在编译时遇到这个错误:

 Main.hs:8:22:
    Couldn't match type ‘Skyline -> Skyline’ with ‘[Coordenada]’
    Expected type: Skyline
      Actual type: Skyline -> Skyline
    Probable cause: ‘combina’ is applied to too few arguments
    In the expression:
      combina
        (resuelveSkyline (fst (divide (xs))), 
         resuelveSkyline (snd (divide (xs))))
    In an equation for ‘resuelveSkyline’:
        resuelveSkyline xs
          = combina
              (resuelveSkyline (fst (divide (xs))), 
               resuelveSkyline (snd (divide (xs))))

我知道合并还没有完成,但我想一点一点地尝试。

我有西班牙语版本,因为我必须强制使用这些函数名称(教授要求我们)。 我将解释每种方法。

resuelveSkyline 有一个 Edificio 列表作为输入,并返回一个 Skyline,它的主要功能。 edificioASkyline 将建筑物作为输入并将其转换为天际线划分采用列表并返回具有相同大小的 2 个列表。 组合采用 2 条天际线并返回一条与两者合并的新天际线。

假设您要定义func :: A -> B -> C 定义 func 的语法是:

func :: A -> B -> C
func a b = ...
  -- ^^^

但是,如果您使用(a,b) ,则不是使用两个单独的参数,而是一对:

--      vvvvv
func :: (A,B) -> C
func (a,b) = ...
--   ^^^^^

但是, GHC 在这一行中只查看combina的类型签名:

resuelveSkyline xs = combina (resuelveSkyline(fst(divide(xs))),resuelveSkyline(snd(divide(xs))))

所以,虽然你已经定义combina工作的元组,它不键入检查。 请注意, combina's定义也不会与其声明的类型统一。

话虽这么说,如果你改变的类型combina并引进帮手,可以使你的代码容易得多:

combina :: (Skyline, Skyline) -> Skyline
combina  (a,b) = ...

both :: (a -> b) -> (a,a) -> (b,b)
both f (x,y) = (f x, f y)

resuelveSkyline xs = combina (both resuelveSkyline (divide xs))

练习

  1. 您可以将任何函数从(a, b) -> c更改为a -> b -> c 编写一个函数来完成该功能:

     fromPairFunc :: ((a,b) -> c) -> (a -> b -> c) fromPairFunc f = ...
  2. 你也可以做相反的事情。 编写相应的函数:

     toPairFunc :: (a -> b -> c) -> ((a,b) -> c) toPairFunc f = ...
  3. 在你的原代码,不改变的类型combina ,但纠正其定义和使用toPairFunc在正确的地方。
  4. 在您的原始代码中,更改combina的类型,但不更改定义。 而不是(resuelveSkyline(fst(divide(xs))),resuelveSkyline(snd(divide(xs)))) ,用两个参数调用它(resuelveSkyline(fst(divide(xs))))(resuelveSkyline(snd(divide(xs)))) (resuelveSkyline(fst(divide(xs)))) (resuelveSkyline(snd(divide(xs)))) 您必须在正确的位置使用toPairFunc

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM