2

在下面的代码中,ghc 抱怨歧义。我假设这是因为类型类是开放的(外部代码可以定义新实例并实际上使这个模棱两可)。

如果我能以某种方式关闭类型Indexable类,是否足以使这个想法成为实现基本关联类型的有效方法?

这个问题更多的是关于类型推断的理论方面,而不是关于如何让它在 Haskell 中工作。这里的问题是这样一个系统的理论问题,它会使下面无法进行推理t1吗?允许封闭类型类是否足以t1明确推断?

{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}

class Indexable a where

instance Indexable (String, Int, Char) where
instance Indexable ([(String, a)], String, a) where

test1 :: Indexable (a,b,c) => a -> b -> c
test1 x y = undefined

t1 = test1 "hi" 3 == 'c'

main = return ()

----------------------------------------------------------------
-- indexable.hs:14:6:                                         --
--     No instance for (Indexable ([Char], b0, Char))         --
--       arising from a use of ‘test1’                        --
--     The type variable ‘b0’ is ambiguous                    --
--     Note: there is a potential instance available:         --
--       instance Indexable (String, Int, Char)               --
--         -- Defined at indexable.hs:8:10                    --
--     In the first argument of ‘(==)’, namely ‘test1 "hi" 3’ --
--     In the expression: test1 "hi" 3 == 'c'                 --
--     In an equation for ‘t1’: t1 = test1 "hi" 3 == 'c'      --
--                                                            --
-- indexable.hs:14:17:                                        --
--     No instance for (Num b0) arising from the literal ‘3’  --
--     The type variable ‘b0’ is ambiguous                    --
--     Note: there are several potential instances:           --
--       instance Num Double -- Defined in ‘GHC.Float’        --
--       instance Num Float -- Defined in ‘GHC.Float’         --
--       instance Integral a => Num (GHC.Real.Ratio a)        --
--         -- Defined in ‘GHC.Real’                           --
--       ...plus three others                                 --
--     In the second argument of ‘test1’, namely ‘3’          --
--     In the first argument of ‘(==)’, namely ‘test1 "hi" 3’ --
--     In the expression: test1 "hi" 3 == 'c'                 --
----------------------------------------------------------------
4

1 回答 1

4

这个错误是由可怕的单态限制引起的。用 禁用它NoMonomorphismRestriction

{-# LANGUAGE NoMonomorphismRestriction #-}

这个问题是一个很好的例子,说明你应该在哪里使用MultiParamTypeClassesnewtypes。

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE MultiParamTypeClasses #-}

import Data.Maybe

class Indexable k v c where
    at :: c -> k -> Maybe v

一个普通的列表是Indexableby Int

instance Indexable Int a [a] where
    c `at` k = listToMaybe  . drop k $ c

具有作为关联列表的特殊含义的列表Indexable如果包含在newtype.

newtype Assoc k v = Assoc {getAssoc :: [(k, v)]}

instance (Eq k) => Indexable k v (Assoc k v) where
    c `at` k = fmap snd . listToMaybe  . filter ((== k) . fst) . getAssoc $ c

使用NoMonomorphismRestriction或显式签名,剪断的测试将编译。

-- t1 :: Indexable Int v [Char] => Maybe v
t1 = "hi" `at` (3 :: Int)

可以通过使用或帮助编译器推断所涉及的类型来进一步Indexable改进该类。FunctionalDependenciesTypeFamilies

{-# LANGUAGE FunctionalDependencies #-}

class Indexable k v c | c -> k, c -> v where
    at :: c -> k -> Maybe v
于 2015-02-25T01:23:44.413 回答