如何将该实例方法定义移动到类默认值? [英] How can I move this instance method definition to class default?

查看:91
本文介绍了如何将该实例方法定义移动到类默认值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑此类和示例实例.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆