带有函数的Haskell语法,特别是findMin函数

时间:2017-09-16 23:33:05

标签: function haskell syntax

我在与Haskell的语法上挣扎。这很简单,但我被困住了。

我试图写一个findMin函数,它接受一个列表并找到最小值。这是我的代码,我尝试了很多语法上的东西,以便我能得到任何帮助。

findMin [] = [0]
findMin list = if any < head list then findMin(tail) else take 1

我得到各种类型的错误。出了什么问题?

(如果它有帮助我有面向对象编程的背景)

2 个答案:

答案 0 :(得分:5)

我看到你在评论中已经弄明白了,但我希望能在这里添加一些东西来帮助你。我也觉得我应该快速提一下Haskell已经有一个minimum函数,以防万一有人偶然发现这个并不只是试图学习语言并且实际上需要函数。

首先让我们谈谈类型。我通常希望findMin函数样式返回列表中的最小值而不是该值,因此类型将是: findMin :: (Num a, Ord a) => [a] -> a

=>之前的内容为函数类型添加上下文。这限制了a可能只是有秩序的东西的所有事情(否则我们怎样才能找到最小值)。其次Num a强制a为数字,这是必要的,因为您指定空列表的大小写应为0。

我将解释另外两种编写findMin函数的方法,尝试使它们比你的定义更简洁(Haskell的一个好处是它的简洁程度,我也发现它有助于学习多种可能性)。第一个将使用递归和守卫,第二个将使用列表理解。

我们无法对findMin [] = 0做多少工作,因此我们会将相关信息移到列表中。

我们需要小心使用递归定义,因为最终我们将评估findMin []并始终得到0,因此我们需要在此之前通过定义单个值的大小写来停止递归: findMin [x] = x

当将列表作为参数传递给函数时,您可以将其元素分开并为每个元素指定一个名称,以便(x:xs)表示值x是第一个元素,后跟元素列表{ {1}}。

对于这个定义,我们将自己定义前两个元素,然后是其余元素:

xs

警卫允许我们根据条件对函数定义多个定义。如果findMin (x:y:xs) | x < y = findMin (x:xs) | otherwise = findMin (y:xs) 我们希望摆脱y,因为它不是最小值,因此我们找到x < y的最小值和其余元素x。如果xs不小于x,则最小值为yy中的一个值。

定义此功能的第二种方法是使用列表理解(这是我最喜欢的,因为它特别简洁)。

我们没有使用递归,所以我们不需要一个元素的情况,我们可以保留我们对空列表的定义,直接进入任何带元素的列表:

xs

那么这里发生了什么? findMin xs = head [x | x <- xs, all (>= x) xs]创建了[x | x <- xs]个值列表,其中xx中的所有元素。然后,我们添加一个条件,表示如果xs的{​​{1}}的所有元素都大于或等于all (>= x) xs,我们只需要这些值。

这会产生最小元素的列表。如果最小值出现一次,则可能有一个元素,如果多次出现,则可能有多个元素。无论哪种方式,它们都是相同的,所以我们只使用xs

希望这会有所帮助,并希望您学习Haskell很有趣。如果您有任何问题,请随时询问:)

答案 1 :(得分:0)

在ghci中,这个功能似乎可以解决问题:

    struct hostent* server = gethostbyname([_hostname UTF8String]);
    struct addrinfo *ai;
    struct addrinfo hints;


    memset(&hints, 0x00, sizeof(hints));
    hints.ai_family   = AF_INET;
    hints.ai_socktype = SOCK_STREAM;

    NSString* portString = [NSString stringWithFormat:@"%d", _port];
    getaddrinfo([_hostname UTF8String], [portString cStringUsingEncoding:kCFStringEncodingASCII] , &hints, &ai);

    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    bcopy(server->h_addr, &addr.sin_addr.s_addr, server->h_length);
    addr.sin_port = htons(_port);
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);

    _addr = (struct sockaddr*)&addr;
    int status = connect(sockfd, (struct sockaddr*)&addr, sizeof(addr));
    int status2 = connect(socket(ai->ai_family,ai->ai_socktype,0), ai->ai_addr, ai->ai_addrlen);

我正在学习,因为我试着在这里回答一些问题,所以任何反馈都会受到赞赏。