Haskell map是如何在内部实现的?

Haskell map是如何在内部实现的?,haskell,Haskell,好的,我想实现我的自定义映射,它接收一个复制因子和一个目标列表 输入:Int->[Int] 输出:[[Int]] 例如:2[1,2]------>[1,1],[2,2]] f[1,2,3]->map->[f(1),f(2),f(3)] 当map转到列表的下一个元素时,f(1)应该发生什么?我应该如何用f(1)替换1 这是我最初的解决方案,但它确实复制了最初的列表,而不是每个元素 replicate::Int->[Int]->[[Int]] replicate 1 x=x replic

好的,我想实现我的自定义映射,它接收一个复制因子和一个目标列表

输入:
Int->[Int]

输出:
[[Int]]

例如:
2[1,2]------>[1,1],[2,2]]

f[1,2,3]
->map->
[f(1),f(2),f(3)]

当map转到列表的下一个元素时,f(1)应该发生什么?我应该如何用f(1)替换1

这是我最初的解决方案,但它确实复制了最初的列表,而不是每个元素

replicate::Int->[Int]->[[Int]]
replicate 1 x=x
replicate factor (x:xs)= go factor [] (x:xs) where
                         go factor ls (x:xs) =go factor (repl factor x):ls xs 
                         repl 1 nr=nr
                         repl times nr=nr:repl (times-1) nr

有两个问题会阻止您的代码编译:

  • null
    函数的类型为
    [a0]->Bool
    ,但您正在应用它 在列表的元素上,因此您希望它是
    Int->Bool

  • 结果
    fx
    不应该被推到输入的尾部,而是 应推送到函数递归调用的结果中:
    fx:(mymap fxs)
    而不是
    fx:xs

  • 因此,以下代码应起作用:

    mymap :: (Int -> [Int]) -> [Int]-> [[Int]]
    mymap f (x:xs) = if null xs then [] else f x : (mymap f xs)
    
    顺便说一句,标准库通过模式匹配提供了可读性强(而且是多态性的):

    map :: (a -> b) -> [a] -> [b]
    map _ []     = []
    map f (x:xs) = f x : map f xs
    

    有两个问题会阻止您的代码编译:

  • null
    函数的类型为
    [a0]->Bool
    ,但您正在应用它 在列表的元素上,因此您希望它是
    Int->Bool

  • 结果
    fx
    不应该被推到输入的尾部,而是 应推送到函数递归调用的结果中:
    fx:(mymap fxs)
    而不是
    fx:xs

  • 因此,以下代码应起作用:

    mymap :: (Int -> [Int]) -> [Int]-> [[Int]]
    mymap f (x:xs) = if null xs then [] else f x : (mymap f xs)
    
    顺便说一句,标准库通过模式匹配提供了可读性强(而且是多态性的):

    map :: (a -> b) -> [a] -> [b]
    map _ []     = []
    map f (x:xs) = f x : map f xs
    
    接收复制因子和目标列表的自定义映射

    我不太清楚你要什么

    mymap
    是否接收复制因子,或者
    f

    例如:
    2[1,2]------>[1,1],[2,2]]

    如果希望
    mymap 2[1,2]
    给出
    [[1,1],[2,2]]
    ,则:

    mymap :: Int -> [a] -> [[a]]
    mymap = map . replicate
    
    但是,

    这个函数与内置的
    map:(a->b)->[a]->[b]
    a
    作为
    Int
    b
    作为
    [Int]
    有什么不同?这里,
    mymap
    本身没有任何
    Int
    参数,因此您必须说明
    f
    的参数是复制因子;但是如果
    f23==[3,3]
    ,那么
    f
    就是
    replicate
    ,您可以使用上面的解决方案

    如果愿意,可以使用自己的递归定义编写:

    mymap :: Int -> [a] -> [[a]]
    mymap _ [] = []
    mymap n (x:xs) = myreplicate n x : mymap n xs
    
    myreplicate :: Int -> a -> [a]
    myreplicate 0 _ = []
    myreplicate n x = x : myreplicate (n-1) x
    
    或者您可以使用列表理解而不是
    映射

    mymap :: Int -> [a] -> [[a]]
    mymap n xs = [ replicate n x | x <- xs ]
    
    mymap::Int->[a]->[[a]]
    mymap nxs=[复制nx | x
    接收复制因子和目标列表的自定义映射

    我不太清楚你要什么

    mymap
    是否接收复制因子,或者
    f

    例如:
    2[1,2]------>[1,1],[2,2]]

    如果希望
    mymap 2[1,2]
    给出
    [[1,1],[2,2]]
    ,则:

    mymap :: Int -> [a] -> [[a]]
    mymap = map . replicate
    
    但是,

    这个函数与内置的
    map:(a->b)->[a]->[b]
    a
    作为
    Int
    b
    作为
    [Int]有何不同
    ?在这里,
    mymap
    本身没有任何
    Int
    参数,因此您的意思是
    f
    的参数是复制因子;但是如果
    f23==[3,3]
    ,那么
    f
    就是
    replicate
    ,您可以使用上面的解决方案

    如果愿意,可以使用自己的递归定义编写:

    mymap :: Int -> [a] -> [[a]]
    mymap _ [] = []
    mymap n (x:xs) = myreplicate n x : mymap n xs
    
    myreplicate :: Int -> a -> [a]
    myreplicate 0 _ = []
    myreplicate n x = x : myreplicate (n-1) x
    
    或者您可以使用列表理解而不是
    映射

    mymap :: Int -> [a] -> [[a]]
    mymap n xs = [ replicate n x | x <- xs ]
    
    mymap::Int->[a]->[[a]]
    
    mymap n xs=[replicate n x | x我认为您可以实现map而不必在列表上设置限制。我认为您可以以某种方式用其他内容替换列表中的所有元素。不,在后台
    map
    肯定需要使用
    模式构造函数解构其输入,并使用
    值con重构其结果structor(operator)。一旦你有了足够多的有用的高阶函数,比如
    map
    replicate
    ,你就可以利用它们来避免写显式的consing,但它们仍然是隐藏的。这就是我想要的圣杯解释:D谢谢你,先生。我想你可以[(插入这里),(插入这里),(插入此处)]您只能对固定长度的列表执行此操作。@Bercoviciarian甚至
    [foo,bar,baz]
    对于调用
    ;特别是
    foo:bar:baz:[]
    。我认为您可以实现map,而不必在列表上设置约束。我认为您可以以某种方式用其他内容替换列表中的所有元素。不,在后台
    map
    肯定需要使用
    模式构造函数解构其输入,并使用
    值构造函数重构其结果(操作符)。一旦你有了足够多有用的高阶函数,比如
    map
    replicate
    ,你就可以利用它们来避免编写显式的consing,但它们仍然会出现在引擎盖下。这就是我想要的圣杯解释:D谢谢你,先生。我想你可以[(插入这里),(插入这里),(插入这里)]您只能对固定长度的列表执行此操作。@Bercovicadrian甚至
    [foo,bar,baz]
    对于调用
    ;具体来说,
    foo:bar:baz:[]
    。注意:“输入:
    Int->[Int]
    ,输出:
    [[Int]]
    ”表明函数应该具有签名
    (Int->[Int])[[Int]]
    ,它与
    Int->[Int]->[[Int]]]
    非常不同。后者实际上被解析为