首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Haskell中使用类型号生成给定数量的函数

在Haskell中使用类型号生成给定数量的函数
EN

Stack Overflow用户
提问于 2011-05-03 08:13:53
回答 4查看 877关注 0票数 14

假设我已经将自然数编码为Haskell类型,并且我有一种对它们进行加减的方法:

代码语言:javascript
复制
data Zero
data Succ n
-- ...

我见过创建可变函数外观的各种代码,例如this,它允许以下内容:

代码语言:javascript
复制
buildList "polyvariadic" "function" "wut?" :: [String]
-- ["polyvariadic","function","wut?"]

我想知道的是,我是否可以在此基础上构建一个函数,该函数将只接受与类型number的实例相对应的参数数量。我想要做的看起来像这样:

代码语言:javascript
复制
one = Succ Zero
two = Succ one
three = Succ two

threeStrings :: String -> String -> String -> [String]
threeStrings = buildList three

threeStrings "asdf" "asdf" "asdf"
-- => ["asdf","asdf","asdf"]

threeStrings "asdf"
-- type checker is all HOLY CHRIST TYPE ERROR

threeStrings "asdf" "asdf" "asdf" "asdf"
-- type checker is all SWEET JESUS WHAT YOU ARE DOING

我知道这很愚蠢,可能是在浪费我的时间,但这看起来像是周末的乐趣。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-05-03 08:32:45

好的。是。当然,通过线程化递归实例的数值类型。

首先,一些样板文件:

代码语言:javascript
复制
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE EmptyDataDecls         #-}
{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE FlexibleContexts       #-}
{-# LANGUAGE ScopedTypeVariables    #-}

您的nats:

代码语言:javascript
复制
data Zero
data Succ n

一个用于可变函数的递归构建器,现在有一个n参数:

代码语言:javascript
复制
class BuildList n a r | r -> a where
    build' :: n -> [a] -> a -> r

一个基本情况:当我们到达Zero时停止

代码语言:javascript
复制
instance BuildList Zero a [a] where
    build' _ l x = reverse $ x:l

否则,递减1并递归:

代码语言:javascript
复制
instance BuildList n a r => BuildList (Succ n) a (a->r) where
    build' (_ :: Succ n) l x y = build' (undefined :: n) (x:l) y

现在,我们只想循环3次,所以把它写下来:

代码语言:javascript
复制
build :: BuildList (Succ (Succ Zero)) a r => a -> r
build x = build' (undefined :: Succ (Succ Zero)) [] x

好了。

测试:

代码语言:javascript
复制
> build "one" "two" "three" :: [[Char]]
["one","two","three"]

任何更少或更多都是错误:

代码语言:javascript
复制
*Main> build "one" "two" "three" "four" :: [[Char]]

<interactive>:1:1:
    No instance for (BuildList Zero [Char] ([Char] -> [[Char]]))

*Main> build "one" "two" :: [[Char]]

<interactive>:1:1:
    No instance for (BuildList (Succ Zero) [Char] [[Char]])
票数 18
EN

Stack Overflow用户

发布于 2011-05-06 07:42:11

我看到了你的函数依赖、多参数、空数据类型、灵活的作用域类型变量,并建议你使用Haskell98版本!它使用hackage上提供的HoleyMonoid:

代码语言:javascript
复制
{-# LANGUAGE NoMonomorphismRestriction #-}

import Prelude hiding (id, (.))
import Control.Category
import Data.HoleyMonoid

suc n = later (:[]) . n

zero  = id
one   = suc zero
two   = suc one
three = suc two

buildList = run

测试(可以随意省略任何类型签名):

代码语言:javascript
复制
> run three "one" "two" "three"
["one","two","three"]
票数 9
EN

Stack Overflow用户

发布于 2011-05-06 17:17:19

内联Martijn的代码给出了一个非常简单的解决方案:

代码语言:javascript
复制
zero xs = xs
suc n xs x = n (xs ++ [x])
buildList n = n []
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5863809

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档