我是Haskell的新成员,以下是我的问题:
给出这个课程:
class MyClass a where
foo :: a -> [a]
然后我有一个更具体的子类:
class (MyClass a) => SubClass a where
foo param = [bar param]
bar :: a -> a
但它没有按预期工作。我期待在SubClass
的定义中设置默认实现,但事实并非如此。我需要单独定义MyClass
的实例,但这听起来很愚蠢。当我知道某个子类肯定满足某些属性时,如何实现默认实现?
更具体地说,我想在Haskell中表达when a class satisfies some properties, some functions for its parent can have default implementation
。在我的示例中,SubClass
具有属性bar
,因此我知道foo
肯定是以这种方式定义的。
这个问题的一般形式是,通过使用类和实例重用是一个好主意吗?
我发现了这篇文章:Inclusion of typeclasses with default implementation in Haskell
它非常接近,但仍然没有完全回答我的问题而且他们的形式有点不同。
答案 0 :(得分:6)
阐述丹尼尔的答案:
假设您有一个新的数据类型MyData
,定义为
data MyData = D1 | D2
您希望MyData
成为SubClass
的实例。你先尝试一下这个明显的解决方案。
instance SubClass MyData where
bar x = case x of { D1 -> D2 ; D2 -> D1 }
然而,对类型签名的快速检查表明,这不会起作用,因为类型必须是MyClass
的实例才能成为SubClass
的实例。因此,您将MyData
设为MyClass
的实例。
instance MyClass MyData
同样,这会引发错误,因为foo
包含在MyClass
的最小完整定义中。要使您的实例起作用,您必须手动定义foo
,从而违背默认声明的目的。
简而言之,在基本的Haskell98(或Haskell2010,就此而言)中无法做到这一点。但值得庆幸的是,GHC提供了一个名为DefaultSignatures
的有用扩展。所以,使用丹尼尔的例子:
{-# LANGUAGE DefaultSignatures #-}
class MyClass a where
foo :: a -> [a]
default foo :: SubClass a => a -> [a]
foo param = [param]
class MyClass a => SubClass a where
bar :: a -> a
现在,您可以定义实例,它们将按预期工作。此解决方案的缺点是默认定义必须在MyClass
中定义,但这是必要的。 foo
的定义属于MyClass
(或其实例声明之一)的定义,因此如果您能够在{{1}的定义中定义foo
的默认声明,Haskell的类型隔离将被破坏。
答案 1 :(得分:4)
这可以通过<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.full.js"></script>
<p>With an inline search box</p>
<select style="width: 200px" class="inline-search">
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AZ">Arizona</option>
</select>
<p>With the search box in the dropdown</p>
<select style="width: 200px" class="dropdown-search">
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AZ">Arizona</option>
</select>
<p>With the selection hidden when it is focused</p>
<select style="width: 200px" class="autocomplete">
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AZ">Arizona</option>
</select>
:
DefaultSignatures
在ghci中测试:
{-# LANGUAGE DefaultSignatures #-}
class MyClass a where
foo :: a -> [a]
default foo :: SubClass a => a -> [a]
foo param = [param]
class MyClass a => SubClass a where
bar :: a -> a