Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.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
List 您可以使用(=)<*&燃气轮机;相反。它是如何工作的?_List_Haskell_Reverse_Palindrome - Fatal编程技术网

List 您可以使用(=)<*&燃气轮机;相反。它是如何工作的?

List 您可以使用(=)<*&燃气轮机;相反。它是如何工作的?,list,haskell,reverse,palindrome,List,Haskell,Reverse,Palindrome,我试着用这些类型来处理这个问题,但是我仍然很难理解它是如何工作的 鉴于: > :t (==) (==) :: Eq a => a -> a -> Bool > :t (<*>) (<*>) :: Applicative f => f (a -> b) -> f a -> f b > :t reverse reverse :: [a] -> [a] > :t (==) <*> reve

我试着用这些类型来处理这个问题,但是我仍然很难理解它是如何工作的

鉴于:

> :t (==)
(==) :: Eq a => a -> a -> Bool

> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b

> :t reverse
reverse :: [a] -> [a]

> :t (==) <*> reverse
(==) <*> reverse :: Eq a => [a] -> Bool
:t(=)
(==)::等式a=>a->a->Bool
>:t()
()::应用程序f=>f(a->b)->f a->f b
>:t倒档
反向::[a]->[a]
>:t(=)反向
(==)反向::等式a=>[a]->Bool
直观地说,我可以理解,它将等式运算符与reverse结合在一起,这样它就创建了一个函数来检查反转列表是否与原始列表相等,但这实际上并没有比已经非常明显的内容更多的信息


有人能更详细地分析一下这里实际发生的事情吗?

()

特别是,专门用于
(>)k
()
类型为

(<*>) :: (k -> a -> b) -> (k -> a) -> (k -> b)
(==) <*> reverse = \k -> (==) k (reverse k)
                 = \k -> k == reverse k
()::(k->a->b)->(k->a)->(k->b)
因此,应用程序
(==)反向

(<*>) :: (k -> a -> b) -> (k -> a) -> (k -> b)
(==) <*> reverse = \k -> (==) k (reverse k)
                 = \k -> k == reverse k
(==)反向=\k->(==)k(反向k)
=\k->k==反向k

i、 e.它检查列表是否与其反面相同。

Chris Taylor的回答恰好正确,但我发现更直观的另一种看待它的方式是:函数类型的
Applicative
实例所做的是:

  • “Feed”同一参数值到两个参数类型相同的函数
  • 将它们的结果与另一个函数相结合
  • 所以基本上,如果你有
    f::t->a
    g::t->b
    Applicative
    实例允许你在
    a
    b
    结果上映射函数
    h::a->b->c
    ,前提是
    f
    g
    将被输入相同的参数

    因此,请考虑如何以一种不复杂的方式编写回文测试:

    palindrome :: Eq a => [a] -> Bool
    palindrome xs = xs == reverse xs
    
    xs
    在定义的右侧出现两次:一次作为
    =
    的参数,第二次作为
    反向
    的参数。这会自动告诉您,可能有一种方法可以使用
    (>)t
    应用程序实例来消除重复。另一种可能更直观的方法是首先将函数重写为:

    palindrome xs = id xs == reverse xs
    
    …其中,
    id x=x
    是标识函数,它只返回其参数(并且是标准库函数)。现在,您可以使用标准的
    Applicative
    习惯用法(
    fa0…an
    )将其改写为:

    函数组合最重要的特性之一是,对于任何函数
    f

    f . id = f
    
    因此,将其应用于上面的
    回文
    版本,我们得到:

    -- Since `f . id = f` for all `f`, then `(==) <$> id` is just `(==)`:
    palindrome = (==) <*> reverse
    
    --自'f。id=f`对于所有的`f`,那么`(==)id`就是`(==)`:
    回文=(==)反向
    
    你所说的
    (>)k
    是什么意思?一些背景:
    ((>)t
    是“一个以
    t
    作为输入的函数”,在你的例子中
    t
    字符串。的应用程序实例,它接收一个
    字符串
    ,并将其传递给第一个函数
    f
    ,然后返回另一个函数
    f'
    。它将相同的字符串传递给第二个函数,返回某种类型的值;然后用返回值调用
    f'
    。因此
    (fg)x==fx(gx)
    @amalloy我认为我的很多困惑来自
    的类型签名是如何变化的。例如
    f(a->b)
    如何变成
    (k->a->b)
    。为什么
    (>)k
    会出现这种情况?它的类型签名没有改变,而是我们使用了更专门的版本
    适用于任何应用程序,就像
    ==
    适用于任何等式一样。
    ()::Applicative f=>f(a->b)->f a->f b
    ,在我们的例子中是
    f:(->)String)
    。因此,我们替换
    f
    ,得到
    ():(String->a->b)->(String->a)->(String->b)
    。此外,
    a::String
    b::Bool
    ,所以
    ():(String->String->Bool)->(String->String)->(String->Bool)
    。最后,删除无关的
    ()
    ,得到
    ()::(String->String->Bool)->(String->String)->String->Bool
    。为什么你总是要想出好的、清晰的答案呢?两个月后再回来会更有意义。谢谢
    f . id = f
    
    -- Since `f . id = f` for all `f`, then `(==) <$> id` is just `(==)`:
    palindrome = (==) <*> reverse