如何创建一个接受Num和Maybe Num的函数?

时间:2017-12-20 21:26:40

标签: haskell

我目前正在学习Haskell中的类型类,现在我正在尝试创建一个适用于Maybe和Num的增量函数。但是,我现在有点卡住了。有人可以帮我正确的方向吗? (以下错误)

编辑:我在编译过程中使用-XUndecidableInstances和-XFlexibleInstances作为编译器建议的参数,考虑到-XOverlappingInstances(如注释中所示)已弃用且似乎不起作用。

-- maybenum.hs
class SomeNum a where
  inc' :: a -> Int

instance Num a => SomeNum a where
  inc' n = inc' (Just n)

instance Num a => SomeNum (Maybe a) where
  inc' Nothing = 1
  inc' (Just n) = n + 1

main :: IO ()
main = do
  print $ inc' (Just 0)
  print $ inc' 5
  print $ inc' Nothing

这是我得到的错误:

[1 of 1] Compiling Main             ( maybenum.hs, maybenum.o )

maybenum.hs:5:12: error:
    • Overlapping instances for SomeNum (Maybe a)
        arising from a use of ‘inc'’
      Matching instances:
        instance Num a => SomeNum a -- Defined at maybenum.hs:4:10
        instance Num a => SomeNum (Maybe a) -- Defined at maybenum.hs:7:10
    • In the expression: inc' (Just n)
      In an equation for ‘inc'’: inc' n = inc' (Just n)
      In the instance declaration for ‘SomeNum a’

maybenum.hs:9:19: error:
    • Couldn't match expected type ‘Int’ with actual type ‘a’
      ‘a’ is a rigid type variable bound by
        the instance declaration at maybenum.hs:7:10
    • In the expression: n + 1
      In an equation for ‘inc'’: inc' (Just n) = n + 1
      In the instance declaration for ‘SomeNum (Maybe a)’
    • Relevant bindings include
        n :: a (bound at maybenum.hs:9:14)
        inc' :: Maybe a -> Int (bound at maybenum.hs:8:3)

maybenum.hs:13:11: error:
    • Overlapping instances for SomeNum (Maybe a1)
        arising from a use of ‘inc'’
      Matching instances:
        instance Num a => SomeNum a -- Defined at maybenum.hs:4:10
        instance Num a => SomeNum (Maybe a) -- Defined at maybenum.hs:7:10
    • In the second argument of ‘($)’, namely ‘inc' (Just 0)’
      In a stmt of a 'do' block: print $ inc' (Just 0)
      In the expression:
        do { print $ inc' (Just 0);
             print $ inc' 5;
             print $ inc' Nothing }

maybenum.hs:13:22: error:
    • Ambiguous type variable ‘a1’ arising from the literal ‘0’
      prevents the constraint ‘(Num a1)’ from being solved.
      Probable fix: use a type annotation to specify what ‘a1’ should be.
      These potential instances exist:
        instance Num Integer -- Defined in ‘GHC.Num’
        instance Num Double -- Defined in ‘GHC.Float’
        instance Num Float -- Defined in ‘GHC.Float’
        ...plus two others
        (use -fprint-potential-instances to see them all)
    • In the first argument of ‘Just’, namely ‘0’
      In the first argument of ‘inc'’, namely ‘(Just 0)’
      In the second argument of ‘($)’, namely ‘inc' (Just 0)’

maybenum.hs:14:11: error:
    • Overlapping instances for SomeNum a0 arising from a use of ‘inc'’
      Matching instances:
        instance Num a => SomeNum a -- Defined at maybenum.hs:4:10
        instance Num a => SomeNum (Maybe a) -- Defined at maybenum.hs:7:10
      (The choice depends on the instantiation of ‘a0’
       To pick the first instance above, use IncoherentInstances
       when compiling the other instance declarations)
    • In the second argument of ‘($)’, namely ‘inc' 5’
      In a stmt of a 'do' block: print $ inc' 5
      In the expression:
        do { print $ inc' (Just 0);
             print $ inc' 5;
             print $ inc' Nothing }

maybenum.hs:14:16: error:
    • Ambiguous type variable ‘a0’ arising from the literal ‘5’
      prevents the constraint ‘(Num a0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘a0’ should be.
      These potential instances exist:
        instance Num Integer -- Defined in ‘GHC.Num’
        instance Num Double -- Defined in ‘GHC.Float’
        instance Num Float -- Defined in ‘GHC.Float’
        ...plus two others
        (use -fprint-potential-instances to see them all)
    • In the first argument of ‘inc'’, namely ‘5’
      In the second argument of ‘($)’, namely ‘inc' 5’
      In a stmt of a 'do' block: print $ inc' 5

maybenum.hs:15:11: error:
    • Overlapping instances for SomeNum (Maybe a2)
        arising from a use of ‘inc'’
      Matching instances:
        instance Num a => SomeNum a -- Defined at maybenum.hs:4:10
        instance Num a => SomeNum (Maybe a) -- Defined at maybenum.hs:7:10
    • In the second argument of ‘($)’, namely ‘inc' Nothing’
      In a stmt of a 'do' block: print $ inc' Nothing
      In the expression:
        do { print $ inc' (Just 0);
             print $ inc' 5;
             print $ inc' Nothing }

1 个答案:

答案 0 :(得分:3)

以下是经过调整的代码:

[INFO ] 2017-12-20 17:00:08.591 [main] ProducerConfig - ProducerConfig values: 
    acks = 1
    batch.size = 16384
    bootstrap.servers = [localhost:9092]
    buffer.memory = 33554432
    ...

这符合我的意图:

services.AddAuthentication()
        .AddJwtBearer(options =>
        {
            // Jwt options.
        });

services.ConfigureApplicationCookie(options =>
{
    // Cookie settings
});

我根据我认为您对此代码的意图进行了一些更改。以下是对每个的解释:

第一次更改:{-# LANGUAGE FlexibleInstances, UndecidableInstances #-} class SomeNum a where inc' :: a -> Int instance {-# OVERLAPPABLE #-} Integral a => SomeNum a where inc' n = fromIntegral n + 1 instance Integral a => SomeNum (Maybe a) where inc' Nothing = 1 inc' (Just n) = fromIntegral n + 1

您说λ> inc' 1 2 λ> inc' (Just 1) 2 λ> inc' Nothing 1 已被弃用是对的,但您没有注意到它已被弃用,而不是{-# OVERLAPPABLE #-}。这就是我所添加的内容:

-XOverlappingInstances

这是必要的补充,因为您为{#- OVERLAPPABLE #-}定义了instance {-# OVERLAPPABLE #-} (...)的单独实例,这会导致您遇到的冲突。对于我所做的更改,这实际上并不是必需的,但如果确实再次将限制从Num更改为Maybe,则可以节省您的跌幅。

第二次更改:Integral

您无法从Num转换为Integral a =>,因为Num函数似乎建议(请记住Int是{的实例{1}}。)所以,我调整了限制:

inc'

这也很明显简化了Float实施。请注意Num的使用。我不完全确定这是否有意,但我还没有指明,所以我猜不到。

我希望这会有所帮助。如果这不完全符合您的预期,请尝试自行调整,并探索这些语言扩展的行为方式。