如何将该实例方法定义移动到类默认值? [英] How can I move this instance method definition to class default?
问题描述
请考虑此类和示例实例.
Consider this class, and an example instance.
目的是提供一个类型级别开关,该类型级别开关允许将基本类型(在这种情况下为Int
)转换为经过验证的谓词子类型,以备将来使用.诚然,该类在某种程度上是人为设计的,但是我从实际代码中提取了该类,并且将使用更有用的方法填充该类,除非我被卡住了.
The purpose is to provide a type level switch that allows to convert the base type — Int
, in this case, — to a proven predicate subtype, for future use. Granted, the class is somewhat contrived, but I extracted it from actual code, and I would populate it with more useful methods, save that I am stuck.
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE TypeApplications #-}
module Collection where
import Data.Tagged
-- $setup
--
-- λ :set -XTypeApplications
class Collected phantom
where
type Element phantom = r | r -> phantom
type Element phantom = Tagged phantom Int
type Collection phantom = r | r -> phantom
type Collection phantom = Tagged phantom [Int]
collection :: Collection phantom
inCollection :: Int -> Maybe (Element phantom)
data Primes
instance Collected Primes
where
type Element Primes = Tagged Primes Int
type Collection Primes = Tagged Primes [Int]
collection = Tagged [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
-- inCollection :: Int -> Maybe (Element Primes)
inCollection element
| element `elem` unTagged (collection @Primes) = Just $ Tagged element
| otherwise = Nothing
-- ^
-- λ inCollection @Primes 7
-- Just (Tagged 7)
-- λ inCollection @Primes 8
-- Nothing
(这是一个可运行的代码,具有按书面要求通过的repl测试.)
我将处理同一个基本类型上的几个子类型,这些子类型仅因collection
的定义而不同,而证明方法是始终查找.因此,没有理由没有该方法的默认代码.但是,我无法设计这样的代码.我的第一个草稿无法进行类型检查,而第二个草稿经过调整后可以运行,但似乎没有终止.
I will be dealing with several subtypes over the same base type that only differ by the definition of collection
, while the method of proof is consistently lookup. So there is no reason not to have a default code for that method. However, I was not able to devise such code. My first draft fails to type check, while the second, adjusted draft runs, but does not seem to terminate.
这是初稿:
...
{-# LANGUAGE DefaultSignatures #-}
...
class Collected phantom
...
inCollection :: Int -> Maybe (Element phantom)
default inCollection :: ( Element phantom ~ Tagged phantom Int
, Collection phantom ~ Tagged phantom [Int] )
=> Int -> Maybe (Element phantom)
inCollection element
| element `elem` unTagged collection = Just $ Tagged element
| otherwise = Nothing
...
这是第二个:
...
{-# LANGUAGE ScopedTypeVariables #-}
...
class Collected phantom
...
inCollection :: ...
default inCollection :: ...
inCollection ...
where
collection = (collection :: Collection phantom)
(仅显示添加的部分.实例中相应的方法定义已删除.在第二稿中,除了编译指示外,唯一的添加项是尝试键入collection
的最后一行.)
(Only the added parts are shown. The corresponding method definition in the instance was removed. In the second draft, the only addition aside from the pragma is the last line that attempts to type collection
.)
出什么问题了?该怎么办?
What is the problem? What can be done?
推荐答案
似乎可以进行以下操作.这个想法是在默认值(使用collection @phantom
)中以正确的类型实例化collection
,它也需要ScopedTypeVariables
.
It appears that the following will work. The idea is to instantiate collection
at the right type in the default (with collection @phantom
) which also requires ScopedTypeVariables
.
更新:我现在看到这是您尝试进行的第二次尝试.问题在于您的where
子句定义了一个无限循环,因为RHS上的collection
与绑定到LHS上的collection
是相同的(适当地插入facepalm).
Update: I see now that this is what you tried to do with your second attempt. The problem is that your where
clause defined an infinite loop, as the collection
on the RHS is the same collection
being bound on the LHS (insert facepalm as appropriate).
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE TypeApplications #-}
module Collection where
import Data.Tagged
class Collected phantom
where
type Element phantom = r | r -> phantom
type Element phantom = Tagged phantom Int
type Collection phantom = r | r -> phantom
type Collection phantom = Tagged phantom [Int]
collection :: Collection phantom
inCollection :: Int -> Maybe (Element phantom)
default inCollection :: ( Collection phantom ~ Tagged phantom [Int]
, Element phantom ~ Tagged phantom Int)
=> Int -> Maybe (Element phantom)
inCollection element
| element `elem` unTagged (collection @phantom) = Just $ Tagged element
| otherwise = Nothing
data Primes
instance Collected Primes
where
type Element Primes = Tagged Primes Int
type Collection Primes = Tagged Primes [Int]
collection = Tagged [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
这篇关于如何将该实例方法定义移动到类默认值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!