首页 > 解决方案 > Haskell - 为什么我不在范围内:数据构造函数“ZipList”错误

问题描述

我正在从 learn-you-a-haskell 书中学习 Haskell 中的应用函子。但是每当我尝试在 ghci 中输入以下代码时:

:{
instance Applicative ZipList where
        pure x = ZipList (repeat x)
        ZipList fs <*> ZipList xs = ZipList (zipWith (\f x -> f x) fs xs)
:}

我得到三个错误:

<interactive>:137:22: error:
    Not in scope: type constructor or class ‘ZipList’

<interactive>:139:9: error:
    Not in scope: data constructor ‘ZipList’

<interactive>:139:24: error:
    Not in scope: data constructor ‘ZipList’ 

我尝试加载:

import Data.List
import Data.Char

我尝试搜索 ZipList 没有成功。

我尝试在没有实例声明的情况下运行接下来的几个表达式:

getZipList $ (+) <$> ZipList [1,2,3] <*> ZipList [100,100,100]

但它们也因以下错误而失败:

<interactive>:142:1: error:
    Variable not in scope: getZipList :: f0 Integer -> t

<interactive>:142:22: error:
    Data constructor not in scope: ZipList :: [Integer] -> f0 Integer

<interactive>:142:42: error:
    Data constructor not in scope: ZipList :: [Integer] -> f0 Integer

我也尝试搜索并找到了这个答案: Haskell ZipList Applicative 但这对我没有帮助。

标签: haskelltypeclass

解决方案


ZipList已经存在Control.Applicative并使用Applicative那里定义的实例。您无法重新定义该实例。

>> import Control.Applicative
>> getZipList $ (+) <$> ZipList [1,2,3] <*> ZipList [100,100,100]
[101,102,103]
>> getZipList $ liftA2 (+) (ZipList [1,2,3]) (ZipList [100,100,100])
[101,102,103]

要定义你自己的,你必须定义一个我们读为“ prime”的新的: ZipList'ZipList

-- >> getZipList' $ (+) <$> ZipList' [1,2,3] <*> ZipList' [100,100,100]
-- [101,102,103]
newtype ZipList' a = ZipList' { getZipList' :: [a] }

instance Functor ZipList' where
  fmap f (ZipList' as) = ZipList' (fmap f as)

instance Applicative ZipList' where
  pure a = ZipList' (repeat a)

  ZipList' fs <*> ZipList' xs = ZipList' (zipWith (\f x -> f x) fs xs)

也可以导出Functorfmap我建议为, pure,编写实例签名(<*>)

{-# Language DeriveFunctor #-}
{-# Language DerivingStrategies #-}
{-# Language InstanceSigs #-}

import Control.Applicative (liftA2)

newtype ZipList' a = ZipList' { getZipList' :: [a] }
  deriving
  stock Functor

-- instance Functor ZipList' where
--   fmap :: (a -> a') -> (ZipList' a -> ZipList' a')
--   fmap f (ZipList' as) = ZipList' (fmap f as)

instance Applicative ZipList' where
  pure :: a -> ZipList' a
  pure a = ZipList' (repeat a)

  (<*>) :: ZipList' (a -> b) -> ZipList' a -> ZipList' b
  ZipList' fs <*> ZipList' xs = ZipList' (zipWith ($) fs xs)

  liftA2 :: (a -> b -> c) -> (ZipList' a -> ZipList' b -> ZipList' c)
  liftA2 (·) (ZipList' as) (ZipList' bs) = ZipList' (zipWith (·) as bs)

你可以(\f x -> f x)写成($)id


推荐阅读