错误:不在范围内。为什么会这样呢?

时间:2018-12-02 20:54:45

标签: haskell

我需要根据数据类型 Int'为类 Enum 定义一个实例。我只需要定义函数 toEnum fromEnum 。 例如:映射fromEnum [减一..加(成功的一)]-> [-1,0,1,2]

data PosNat = One | Succ' PosNat 
data Int' = Zero' | Plus PosNat | Minus PosNat 

 instance Enum Int' where
  toEnum 0 = Zero'
  toEnum n | n>0 = Plus (toPosNat n )
  toEnum n | n<0 = undefined -- Minus (toPosNat n) 
    where
      toPosNat :: a -> PosNat
      toPosNat 1 = One 
      toPosNat n | n>1 = (Succ' (toPosNat (n-1)) )
      toPosNat n | n<1 = (Succ' (toPosNat (n+1)) )

问题是,出现以下错误:

Variable not in scope: toPosNat :: Int -> PosNat
   |
62 |   toEnum n | n>0 = Plus (toPosNat n )
   |  

感谢您的帮助! :)

2 个答案:

答案 0 :(得分:4)

where子句附加到单个模式的所有防护。您已经使用三个单独的模式定义了函数,因此where子句仅附加到它们的最后一个。要解决此问题,只需将最后两个模式(相同的,减去警戒线)一起滚动:

 instance Enum Int' where
   toEnum 0 = Zero'
   toEnum n | n>0 = Plus (toPosNat n )
            | n<0 = Minus (toPosNat n) 
     where
       toPosNat :: a -> PosNat
       toPosNat 1 = One 
       toPosNat n | n>1 = (Succ' (toPosNat (n-1)))
                  | n<1 = (Succ' (toPosNat (n+1)))

我对toPosNat进行了相同的更改,因为这是更好的样式,但是在这种情况下没有语义上的影响。

答案 1 :(得分:2)

您需要将toPosNat提升为顶级功能,例如:

 instance Enum Int' where
  toEnum 0 = Zero'
  toEnum n | n>0 = Plus (toPosNat n )
  toEnum n | n<0 = undefined -- Minus (toPosNat n) 

 toPosNat :: a -> PosNat
 toPosNat 1 = One 
 toPosNat n | n>1 = (Succ' (toPosNat (n-1)) )
 toPosNat n | n<1 = (Succ' (toPosNat (n+1)) )

代码中的where子句仅在第三种情况下可见,而在第二种情况下不可见。