代码之家  ›  专栏  ›  技术社区  ›  Expedito

如何让Haskell将函数识别为应用函子

  •  0
  • Expedito  · 技术社区  · 5 年前

    我是哈斯克尔的新手,仍然不知道如何处理他们的类型系统。我的问题是我在玩 序列 好好学你哈斯克尔 . 功能如下:

    sequenceA :: (Applicative f) => [f a] -> f [a]
    sequenceA = foldr (liftA2 (:)) (pure [])
    

    binner :: Int -> [Int -> Int]
    binner n = (map (\x -> bin x) [n, (n-1) .. 1])
      where bin n = (`mod` 2) . (`div` 2^(n-1))
    

    我可以单独使用这些函数。例如,以下内容在GHCi中非常有用:

    sequenceA (binner 4) 10
    

    如果我在GHCi中键入以下内容,

    :t (sequenceA (binner 4))
    

    (sequenceA (binner 4)) :: Int -> [Int]
    

    但是,我不知道如何组合这些函数。直觉上,我应该可以使用GHCi显示的相同类型来执行以下操作:

    binner :: Int -> [Int]
    binner n = foldr (liftA2 (:)) (pure []) $ (map (\x -> bin x) [n, (n-1) .. 1])
      where bin n = (`mod` 2) . (`div` 2^(n-1))
    

    但编译时会出现一个错误:

    无法将类型[a0]与Int匹配 需要类型:[Int]

    我试过修改类型声明,但还没有找到解决方法。

    谢谢你的帮助!

    1 回复  |  直到 5 年前
        1
  •  1
  •   Joseph Sible-Reinstate Monica    5 年前

    你试图使用 sequenceA (binner 4) 基本上 \n -> sequenceA (binner n) . 因为你写的东西需要 Int 你给我的 :t 不,你需要添加 Int -> n :

    binner :: Int -> Int -> [Int]
    binner n = foldr (liftA2 (:)) (pure []) $ (map (\x -> bin x) [n, (n-1) .. 1])
      where bin n = (`mod` 2) . (`div` 2^(n-1))
    

    您可以保留类型,但硬编码4:

    binner :: Int -> [Int]
    binner = foldr (liftA2 (:)) (pure []) $ (map (\x -> bin x) [4, (4-1) .. 1])
      where bin n = (`mod` 2) . (`div` 2^(n-1))
    
    推荐文章